c# - Unit testing void method that creates a new object -
i have method following:
public void executesomecommand() { new mycommand( someint, someenum.enumvalue ).execute(); }
i'd test enum value passed in constructor of icommand object i'm creating correct value. there way can rhino.mocks?
option 1: use seam
the easiest way refactor method seam:
public void executesomecommand() { this.createcommand(someint, someenum.enumvalue).execute(); } // seam protected virtual icommand createcommand(int someint, someenum someenum) { return new mycommand(someint, someenum.enumvalue); }
this way can intercept creation of 'new' operator extending class. when doing hand, might this:
public fakesomeservice : someservice { public int someint; public someenum someenum; protected override command createcommand(int someint, someenum someenum) { this.someint = someint; this.someenum = someenum; return new fakecommand(); } private sealed class fakecommand : command { public override void execute() { } } }
this fake class can used in test methods.
option 2: separate behavior , data
a better way separate data behavior. command has both data (the message) , behavior (handling message). if allowed such change in code base: separate this, instance defining commands , command handlers. here example:
// define interface handling commands public interface ihandler<tcommand> { void handle(tcommand command); } // define specific command public class mycommand { public int someint; public someenum someenum; } // define handler command public class mycommandhandler : ihandler<mycommand> { public void handle(mycommand command) { // here old execute logic } }
now can use dependency injection inject handler class wish test. class this:
public class someservice { private readonly ihandler<mycommand> handler; // inject handler here using constructor injection. public someservice(ihandler<mycommand> handler) { this.handler = handler; } public void executesomecommand() { this.handler.handle(new mycommand { someint = someint, someenum = someenum }); } }
since separated data behavior, easy create fake command handler (or create using rhino mocks) checks if correct command sent handler. manually this:
public class fakehandler<tcommand> : ihandler<tcommand> { public tcommand handledcommand { get; set; } public void handle(tcommand command) { this.handledcommand = command; } }
this fake handler can reused throughout unit testing project. test using fakehandler
this:
[testmethod] public void sometestmethod() { // arrange int expected = 23; var handler = new fakehandler<mycommand>(); var service = new someservice(handler); // act service.executesomecommand(); // assert assert.areequal(expected, handler.handledcommand.someint); }
separating data behavior not makes application more testable. makes application more resilient change. instance, cross-cutting concerns can added execution of commands, without need make changes handler in system. because ihandler<t>
interface single method, easy write decorator can wrap every handler , add things logging, audit trailing, profiling, validation, transaction handling, fault tolerance improvents, etc. can read more in this article.
Comments
Post a Comment