开发者

What are the advantages to wrapping system objects (File, ServiceController, etc) using the Adapter pattern vs. detouring for unit testing?

Consider the following method that stops a service:

Public Function StopService(ByVal serviceName As String, ByVal timeoutMilliseconds As Double) As Boolean

    Try
        Dim service As New ServiceController(serviceName)
        Dim timeout As TimeSpan = TimeSpan.FromMilliseconds(timeoutMilliseconds)

        service.[Stop]()

        If timeoutMilliseconds <= 0 Then
            service.WaitForStatus(ServiceControllerStatus.Stopped)
        Else
            service.WaitForStatus(ServiceControllerStatus.Stopped, timeout)
        End If

        Return service.Status = ServiceControllerStatus.Stopped

    Catch ex As Win32Exception
        'error occured when accessing a system API'
        Return False
    Catch ex As TimeoutException
        Return False
    End Try

End Function

In order to unit test the the method I basically have two options:

  1. Use the Adapter pattern to wrap the ServiceController class's methods I need into an interface I can control. This interface can then be injected into the service class (a.k.a Inversion of Control). This way I have a loosely coupled code and can use 开发者_开发知识库the traditional mocking frameworks to test.
  2. Keep the class as is and use Microsoft Moles (or any other code detouring framework) to intercept the calls to ServiceController to return canned results for testing purposes.

I agree that for domain model code that using the "traditional" unit testing approach makes the most sense as this would lead to a design that is easiest to maintain. However, for code that deals with the .net implementation of Windows API related stuff (file system, services, etc), is there really an advantage to going thru the extra work to get "traditionally" testable code?

It's hard for me to see the disadvantages of using Microsoft Moles for things such as ServiceController (or the File object). I really don't see any advantage of doing the traditional approach in this case. Am I missing anything?


Great question btw.. Just had a look at MS Moles video right now. Although I'm skeptical of MS Unit-testing tools, I must say this one looks interesting. My comparison stands at:

Adapter/Facade

  • Pro: allows you to extract a meaningful role with intention revealing methods. e.g. ServiceManager.StartService(name) could abstract the details {1. ServiceController.GetServices(), 2. handle case where ServiceController.Status != Stopped, 3. ServiceController.Start()}. The mock/fake approach here would involve less work than setting up 3 delegates. Here this approach is an opportunity to improve your design by coming up with meaningful contracts/interfaces (also allows you to hide stuff that you don't care about -- e.g. Winapi semantics, constants, etc)
  • Pro: Mocking frameworks would give you better diagnostics for argument checks, number of times called, expectations not called etc.

Interceptor

  • Pro: Less work if you're just interested in stubbing out a problematic call on a dependency
  • Pro: definitely a good tool in your toolbox when dealing with legacy code (where the fear of change is overwhelming)
  • Con: does it have a MSTest dependency? Initial searches seem to indicate that you need some plugins or extensions if you're not using MSTest.


I believe that this is a good case for mocking and there're some advantages of doing it with IoC:

  • You do actual unit-testing, as your tests aren't testing underlying layers - this would be an integration test -.

  • Easy to plug and unplug a mock object.

  • You don't need to define a "fake" implementation on each stub. You've a "fake", mocked implementation by configuration.

For me, the first reason is the most important.

Why don't to use Moles? Because I believe it's not the right tool for something like this. Moles is more for things like I want a fixed value of DateTime.Now to an specific time, so you can test some code in some situation whenever you want with no troubles.

Moles is an easy way to auto-mock certain methods, properties in specific tests, while IoC+fake, it's to isolate your test.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜