Do you need a stub out with PEX?

When writing unit tests, developers often use mocking frameworks like Moq to create mock or stub objects. These stubs stand in for real dependencies, allowing your tests to focus on the code you are trying to test. But do you really need to stub everything out? What about using partial stubs or even real implementations?

What is stubbing?

Stubbing means creating mocked objects that simulate the behavior of real dependencies. The stubs usually return hardcoded values or do nothing at all. Stubs are configured to help your tests pass without dealing with the full functionality of the actual dependency.

Here are some reasons you might want to use stubbing:

  • Isolate the code under test – Stubs cut out external factors so you can focus on unit testing a specific section of code.
  • Improve speed – Stubbing is faster than relying on real dependencies.
  • Control test data – You can make stubs return consistent, predictable values that are useful for testing.
  • Avoid undesired side effects – Stubbing prevents changes to databases or external systems.

Stubbing with Moq

Moq is a popular .NET mocking framework that makes stubbing easy. Here is an example of using Moq to stub an external service call:

// Create mock object
var mockService = new Mock<IService>(); 

// Stub method call
mockService.Setup(s => s.GetUser(1)).Returns(new User());

We create a mock of the IService interface, then stub the GetUser method to return a fake User object. Now code that calls GetUser will get our stub value back instead of calling the real method.

Do you always need stubs?

While stubbing has advantages, some developers argue you shouldn’t stub out everything. Here are some cases where you may want to use partial stubs or real implementations instead:

When testing interaction logic

If your test involves checking how your code interacts with a dependency, you may want a partial stub that allows you to verify the interaction while still faking implementation details.

When the implementation is trivial

If a dependency does something simple like return a constant, use the real code instead of a stub.

When you need existing functionality

Replacing dependencies with stubs means you lose any existing logic they provide. Sometimes you may want to call the real methods.

When you need side effects

In some cases real behavior like writing to a file is desired during a test. Stubbing would lose these side effects.

When testing the dependency itself

Obviously if you are unit testing the actual dependency, you will want to use the real implementation instead of a stub!

How to use PEX for stubs

PEX is a free extension from Microsoft that does automated unit testing for .NET code using a technique called dynamic symbolic execution. Here are some ways PEX can help generate stubs for you:

Automated stub generation

When PEX runs, it will automatically stub out any external method calls that affect code coverage. This allows it to isolate the code being tested.

Incremental stubbing

PEX starts without stubs initially, then incrementally adds them as needed to guide tests. This means it will only stub the minimum necessary.

Exploring variations

PEX can stub methods using different values to force code down different paths. This provides more thorough testing.

Detecting side effects

If PEX detects a stubbed method call causing an important side effect, it will warn you that a real implementation may be needed for that stub.

Examples of PEX stubbing

Let’s walk through some examples of how PEX handles stubbing situations.

Stubbing external web requests

// Code under test
var response = client.MakeRequest("https://api.data.com/v1/users");

PEX will automatically stub out the web request to isolate the code and avoid real calls during testing.

Stubbing data access code

// Code under test 
var user = db.LoadUser(userId);

Again PEX will stub the database access to isolate the code. The stub will return valid user data to test against.

Stubbing only what’s needed

// Code under test
var cache = cache.Get(key);
if (cache == null) {
  cache = repo.LoadData();
  cache.Set(key, cache) 
}

PEX will stub LoadData since it affects code coverage, but will keep other cache behavior unstubbed.

Exploring stub value variations

// Code under test
var temp = thermometer.Read();
if (temp > 30) {
  // do something
} 

PEX could stub Read to return different temps like 25, 30, and 35 to force both code branches.

Should you stub everything?

PEX shows that comprehensive automated stubbing is possible. But should you stub all dependencies in practice? Here are some guidelines:

  • Stub external services and databases to isolate code. But keep stubs small.
  • Consider potential side effects before stubbing methods.
  • Use real implementations for trivial methods.
  • Stub only what you need to increase code coverage.

Stubbing has its place, but walk the line between isolation and losing important behavior. PEX can handle stubs for you automatically, but think about what type of stub makes sense in each case.

Conclusion

Stubbing can help you isolate code under test and increase unit testing coverage. But blindly stubbing everything limits visibility into how code interacts with its dependencies. PEX provides a good strategy by only adding stubs incrementally as needed. It also warns about potential side effect cases. In summary:

  • Use PEX for automatic smart stub generation
  • Don’t stub what doesn’t need to be stubbed
  • Think about the pros and cons of stubbing each dependency
  • Seek maximum isolation without losing important behavior