1

Very simply what I'm trying to find out is, is there any way of cleanly unit testing this body of code? I can instantiate it and run some assertions but I mean actual unit testing where i would mock the service object to remove any dependancies of the class under test and actually have it test only this class and not its dependent services (in this case ConcreteService).

public class Foo{

    public SomeResult DoSomething(){
        var service = new ConcreteService();
        var foo = service.Execute();
        return foo;
    }

}

My normal approach is to not have this type of object creation in my body of code, but given a scenraio where this cant be changed, what are my options for unit testing it?

AaronHS
  • 1,334
  • 12
  • 29

3 Answers3

5

Given the constraint (that you can't modify/recompile that code), I'm afraid there is not much you can do apart from "integration testing" it - real dependencies, slow tests.

Instantiating a dependency within the method, instead of accepting it as a ctor or method argument makes things difficult.

As Ethan says, there is Moles (but to me personally it just doesn't seem right). I'd prefer a design change than a framework that helps me mask design issues.

Gishu
  • 134,492
  • 47
  • 225
  • 308
  • +1 Answers the main question, "is there any way of *cleanly* unit testing this body of code?" – Jake T. Jun 01 '11 at 05:04
  • im not so much worried about the slow tests... more so that stupid dependancies fail and go looking in the wrong place... but i take your point! – AaronHS Jun 01 '11 at 05:26
  • @Aaron - Another smell. Looking for expected resources in hardcoded locations with no option to override/pass in. I wish I could tell you that there is a way out... Sorry – Gishu Jun 01 '11 at 06:07
  • -1 You can easily unit test this kind of code with a suitable mocking tool, such as TypeMock Isolator (I agree about Moles though, it *is* ugly). Also, I wouldn't say that instantiating a concrete service class inside another is necessarily a design issue. More often than not it has been the best choice, in my experience. – Rogério Jan 13 '12 at 18:13
  • @Rogerio - It's common practice now to accept dependencies as ctor args.. especially if the dependency poses issues for testability. TypeMock Isolator is a paid tool (if I'm not mistaken) so might work if the OP is open to that - IMHO I'd take adding a parameterized ctor over paying for a proprietary tool. – Gishu Jan 14 '12 at 06:26
  • @Gishu - I agree about the commercial tool, but not about the use of constructors for what really are internal dependencies. In the Java world, this is not the dominant practice for DI now; instead, injection into annotated (`@Inject`) private fields is favored, at least by Google Guice and by the Java standard for DI, CDI (personally, I also find it a much better choice, as it avoids breaking the principle of information hiding). – Rogério Jan 16 '12 at 11:06
1

If service.Execute() is virtual, then most mocking frameworks support this. I personally use Rhino.Mocks.

See this question which details the capabilities of using Mocking frameworks on non-Interfaces and discusses the capabilities of mocking frameworks to intercept virtual calls.

If it is not virtual, and you can't change it then you can use Moles. The above mentioned post also mentions the ability to use TypeMock, which I personally haven't used.

The description of Moles on the Microsoft Research Site:

Moles is a lightweight framework for test stubs and detours in .NET that is based on delegates. Moles may be used to detour any .NET method, including non-virtual/static methods in sealed types.

Community
  • 1
  • 1
Ethan Cabiac
  • 4,943
  • 20
  • 36
  • and how would you mock the concreteservice in this context? keeping in mind the concreteclass is instantiated inside the class under test. my understatnding was that mocking frameworks cant handle this scenario, but i could be wrong... – AaronHS Jun 01 '11 at 04:20
  • i dont see how you would be mocking the concreteclass simply by making execute virtual. i know you have to make members virtual when mocking conrete classes, as i've had to do this before with rhinomocks, but its not clear to me how you would supply a mocked concreteclass to the class under test, when its instatntiated in code. thanks for you input! – AaronHS Jun 01 '11 at 04:49
  • @AaronHS - Mocking frameworks can intercept virtual calls. In this case, you are still instantiating `ConcreteService` but the call to `Execute` is intercepted. – Ethan Cabiac Jun 01 '11 at 04:57
1

I know you mentioned that this would be an example of a situation that you couldn't change, but I would fight to refactor the class so that ConcreteService can be injected as a dependency. Refactoring is a much simpler approach to trying to work around a bad design. From what you've posted, I see no reason why you wouldn't be able to do this.

EDIT: FWIW, I agree with @Gishu. If you absolutely cannot modify the class, e.g. you don't own it and you don't have the ability to modify it, then integration tests are the best way to do it. However, if you can see the code and what it's doing, I stand by what I said earlier in that there's really no reason why you shouldn't refactor.

csano
  • 13,266
  • 2
  • 28
  • 45
  • The OP stated that the code couldn't be changed, and even if it were injected as a dependency it would still need a specialized framework to Mock unless you were injecting an interface. – Ethan Cabiac Jun 01 '11 at 05:02
  • @Ethan Semantics. You can't inject an interface. You inject an object that implements an interface. You could also inject a stub that extends a concrete class. Messy, but one of many ways to do it. – csano Jun 01 '11 at 05:13
  • so if i make the method execute() virtual, it will work, but i would be mocking the class under test as opposed to mocking the classes dependancies...? i thought normally you mock dependencies and and use regular instantiation (passing in the mocks) to test the class... or is this just the work around to test these crappy scenarios? – AaronHS Jun 01 '11 at 05:16
  • @j0k, the concrete class stub would still have to have the Execute method marked as virtual for most Mocking frameworks to work. Yes, I should have said "injecting as an instance of an interface". And, since this can't be assumed in a ".net" tagged post, I will explicitly mention that by interface I mean the Gang-of-Four version (i.e. Abstract class, Base class with virtual methods, actual interface, ...) – Ethan Cabiac Jun 01 '11 at 05:18
  • @AaronHS - Are you familiar with dependency injection? If not, I can update my answer with an example of how you can refactor the code you posted to use it. – csano Jun 01 '11 at 05:19
  • @Ethan, agreed re: Execute marked virtual. It's cool - we're both on the same page. I'm just being picky. :) – csano Jun 01 '11 at 05:20
  • @j0k i am. ive been using SM for some time now, however im working on some code that doesnt use DI, and want to know my options. i know ideally id use di and ctor's for my dependancies but im sort of limited at the moment... – AaronHS Jun 01 '11 at 05:21
  • @j0k, @ethan : are my assumptions correct that normally you wouldnt be mocking the class under test? normally wouldnt you be mocking the dep's and using regular instantiation (passing in the mocks)? – AaronHS Jun 01 '11 at 05:23
  • @AaronHs, you are talking about Foo being the class under test, right? If you can "stub" out Execute then you are mocking the dependency, not the CUT. – Ethan Cabiac Jun 01 '11 at 05:27
  • var mock = MockRepository.GenerateMock(); mock.Stub(s => s.DoSomething()).Return("hello"); does this not constitute 'mocking the CUT'? – AaronHS Jun 01 '11 at 05:37
  • @AaronHS - You don't mock the class under test. The class under test is the class that you're testing, which, in this case, is Foo. In common scenarios, you create a mock instance (or stub) of the dependent class and inject into the class when you create an instance of it, assuming you're using constructor injection. This is what I'm suggesting you do with ConcreteService, provided you're able to refactor the code to allow this. – csano Jun 01 '11 at 05:50
  • i know what the common scenario is. im saying to do ethans solution, which is simply to make Execute method virtual in the dependant class, id have to Mock my class under test to actually be able to stub the dependancy. this to me is stupid, but i want to know if there's any merit to it. @Ethan if i go down the path of making execute virtual, sudo code me what my test would look like, as my example above requires a mock of the CUT which makes no sense. we're not talking about making it virtual AND being able to inject it. – AaronHS Jun 01 '11 at 06:24