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

126

CHAPTER 5

Isolation (mock object) frameworks

EventsVerifier verifier = new EventsVerifier(); SomeView view = new SomeView(); verifier.Expect(view, "Load",null,EventArgs.Empty);

view.TriggerLoad(null, EventArgs.Empty);

verifier.Verify();

}

This test assumes we have a class that implements IView, and that the class has a method that triggers the event. The verifier takes the object to test against, the name of the event, and any parameter values that are passed in as part of the event signature. Rhino Mocks currently doesn’t have a decent enough API to test event verification the way

EventsVerifier does.

We’ve covered the basic techniques with Rhino Mocks, so let’s look at a different syntax that it supports: arrange-act-assert.

5.8 Arrange-act-assert syntax for isolation

The record-and-replay model for setting expectations on stubs and mocks has always been a polarizing feature. Some people found it easy to grasp, and some people found it unnatural and cumbersome to write. It also makes tests less readable if you have lots of stubs and expectations in a single test.

The Moq framework changed the landscape in the .NET isolation arena by offering a simplified and concise syntax for setting expectations. Rhino Mocks and Typemock Isolator soon followed.

The idea is based on the way we structure our unit tests today: we arrange objects, act on them, and assert that something is true or false (arrange-act-assert, or AAA). It would be nice if we could use isolation frameworks similarly—to arrange mocks and stubs, set their default behavior, and, only at the end of the test, verify whether a call to the mock object took place.

Listing 5.21 shows a simple test with the record-and-replay syntax, followed by the same test in AAA-style syntax using Typemock Isolator and Rhino Mocks.

Arrange-act-assert syntax for isolation

127

Listing 5.21 Record-and-replay versus AAA-style isolation

[Test]

public void CreateMock_WithReplayAll()

{

MockRepository mockEngine = new MockRepository(); IWebService simulatedService =

mockEngine.DynamicMock<IWebService>(); using (mockEngine.Record())

{

simulatedService.LogError("Filename too short:abc.ext");

}

LogAnalyzer log = new LogAnalyzer(simulatedService); string tooShortFileName = "abc.ext"; log.Analyze(tooShortFileName);

mockEngine.Verify(simulatedService);

}

//the same test using AAA syntax [Test]

public void CreateMock_WithReplayAll_AAA()

{

MockRepository mockEngine = new MockRepository(); IWebService simulatedService =

mockEngine.DynamicMock<IWebService>();

LogAnalyzer log = new LogAnalyzer(simulatedService);

mockEngine.ReplayAll();

 

Moves to

 

log.Analyze("abc.ext");

 

 

act mode

simulatedService.AssertWasCalled(

svc => svc.LogError("name too short:abc.ext"));

}

//the same test using Typemock Isolator AAA syntax [Test]

public void CreateMock_Isolator()

{

IWebService simulatedService = Isolate.Fake.Instance<IWebService>();

LogAnalyzer log = new LogAnalyzer(simulatedService); log.Analyze("abc.ext");

Asserts using Rhino Mocks

128

CHAPTER 5

Isolation (mock object) frameworks

Isolate.Verify.WasCalledWithExactArguments(()=>

simulatedService Asserts using

.LogError("name too short:abs.ext"));

Typemock Isolator

}

Setting up Typemock Isolator

To use Typemock Isolator, you’ll need to first download it from Typemock.com and install it. It’s a commercial product with a 21-day (extendable) evaluation period. Unlike the other frameworks, you can’t just reference a DLL and start using it. It requires a Visual Studio plugin to work, and a special runner to run tests in command-line mode.

To add a reference to Typemock, right-click on the test project in Solution Explorer, and select Add Reference. From there, go to the .NET tab and select both “Typemock Isolator” and “Typemock Isolator—C#” or “Typemock Isolator—VB”. (The product has a special VB-friendly API that solves some VB-specific issues with regard to anonymous delegate usage.)

The main difference between the record-and-replay model and the AAA model is that in AAA we don’t need to record what we expect will happen. We just need to check at the end of the test that something did happen correctly. This makes the test more readable, but you’ll also notice the use of .NET 3.5 lambda syntax in the AAA-style tests. This is an essential part of these new APIs and what makes these syntax changes technically possible.

If you’re not comfortable using lambdas yet, you might be better off using the record-and-replay style until you get used to lambdas, and they’re not an obstacle to understanding the code.

Listing 5.22 shows how you’d use AAA-style stubs with Rhino Mocks and Typemock Isolator.

Listing 5.22 Stubs in AAA-style isolation

[Test]

public void StubThatThrowsException_RhinoMocks()

{

Arrange-act-assert syntax for isolation

129

IWebService simulatedService =

 

 

MockRepository.GenerateStub<IWebService>();

 

Uses

 

simulatedService

 

? extension

.Expect(t => t.LogError(""))

 

 

methods

 

 

.Throw(new Exception("fake exception"))

 

 

w Throws fake

 

 

.Constraints(Is.Anything());

 

 

exception

 

 

 

 

 

 

 

 

 

LogAnalyzer log = new LogAnalyzer(simulatedService); log.Analyze("abc.ext");

}

[Test]

public void StubThatThrowsException_Isolator()

{

IWebService simulatedService = Isolate.Fake.Instance<IWebService>();

Isolate

.WhenCalled(()=>simulatedService.LogError(""))

.WillThrow(new Exception("fake exception"));

Provides

esingle point of entry to API

Throws fake w exception

LogAnalyzer log = new LogAnalyzer(simulatedService); log.Analyze("abc.ext");

}

These tests will fail because we’re throwing a fake exception w from the web service stub. The Expect() method that magically appears on the IWebService interface ? when using Rhino Mocks is due to extension methods that are used in .NET 3.5. With Typemock Isolator, there’s a single point of entry to the API e, so no extension methods are necessary.

Personally, I find that the AAA syntax for Typemock Isolator is more readable than in Rhino Mocks. There are many other facets to the new AAA syntax. You can learn more about it at the websites for the various frameworks.

It’s now time to compare Rhino Mocks to other isolation frameworks in the .NET world.

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