Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Manning.The.Art.of.Unit.Testing.with.Examples.in.dot.NET.Jun.2009.pdf
Скачиваний:
19
Добавлен:
21.03.2016
Размер:
9.67 Mб
Скачать

106

CHAPTER 5

Isolation (mock object) frameworks

What happens if the implementation of log.Analyze() contains an unexpected call to the service, either through an unexpected parameter value or an unexpected method call that we never recorded?

public void Analyze(string fileName)

{

if(fileName.Length<8)

{

// expected "Filename too short:abc.extfile name was too short" service.LogError("bad string");

}

}

The test will fail, but it won’t fail when calling the Verify() method. It will fail before that, during the test run when the call to LogError() is executed. The test will never get to the Verify() line because an exception will be thrown before that. To understand why, we’ll review the idea of strict and nonstrict mocks.

5.3 Strict versus nonstrict mock objects

Let’s discuss what strict and nonstrict mocks mean, and why I consider nonstrict mocks better for most tests.

5.3.1Strict mocks

A strict mock object can only be called by methods that were explicitly set via expectations. Any call that differs either by the parameter values defined or by the method name will usually be handled by throwing an exception. The test will fail on the first unexpected method call to a strict mock object. I say “usually” because whether or not the mock throws an exception depends on the implementation of the isolation framework. Some frameworks allow you to define whether to delay all exceptions until calling verify() at the end of the test.

This means that a strict mock can fail in two ways: when an unexpected method is called on it, or when expected methods aren’t called on it (which is determined by calling Verify()).

Strict versus nonstrict mock objects

107

In Rhino Mocks, strict mocks are created by calling the StrictMock<T> method. Unexpected method call exceptions will always be thrown, even if your test contains a global try-catch clause, which you’d think would catch such an exception thrown from the isolation framework.

5.3.2Nonstrict mocks

Most of the time, nonstrict mocks make for less brittle tests. A nonstrict mock object will allow any call to be made to it, even if it was not expected. As long as the call doesn’t require a return value, it will do what’s necessary for everything in the test to work out.

If a method that needs to return a value is called, and you did not set up a return value when you set up that mock object, a Rhino Mocks nonstrict mock or stub object can return the default value for that method’s return type (0 or null usually). Other frameworks may take different approaches and may throw an exception if the method isn’t configured to return anything.

A nonstrict mock can only fail a test if an expected method was not called. You have to call the Verify(mock) method to find out if such a call is missing from the interaction, or the test will pass.

The example in listing 5.3 uses a strict mock approach, which is why running the test fails mid-test instead of when calling Verify(). By call-

ing MockRepository.DynamicMock<type>() instead of MockReposi-

tory.StrictMock<Type>(), you’ll get a test that only fails on the last line.

Listing 5.4 shows how the test from listing 5.3 would look if we used a nonstrict mock object with Rhino Mocks.

Listing 5.4 Creating a nonstrict mock

[Test]

public void Analyze_TooShortFileName_ErrorLoggedToService()

{

MockRepository mocks = new MockRepository(); IWebService simulatedService =

MockRespository.DynamicMock<IWebService>();

using(mocks.Record())

{

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]