"Stubbing out" a function for unit tests - c#

I have various methods that I would like to unit test using Visual Studio's built in unit testing capability for C#. Things have been going pretty smoothly, but I've run into a scenario where I want to "stub out" a dependency on a particular function call.
Namely, I have some methods that are in the following format:
public class ClassWithMethodsIWantToUnitTest
{
public void myFcn(object someArg)
{
...
LoggerService.Instance.LogMessage("myMessage");
...
}
}
So basically, I want my unit test to simply verify that the call to "LogMessage" has occurred. I don't want to actually check a log file or anything. I want a way to see if the LoggerService line has been hit and executed.
LoggerService is a singleton, and if possible, I don't want to modify the code just for unit testing.
Based on the format of this problem, it seems to me that it should be possible to somehow take control of the code in my unit test. In other words, is there a way for me to make a fake version of LogMessage such that I can use it for my unit test? I don't want the "real" LogMessage function to be called if possible. I just want to test that the code hit the path that called the function.
Does this make any sense? Is this possible?

It certainly makes sense and is not an unknown problem.
Unfortunately you will probably need to change the code, so that it accepts dependency injection. That is, when testing you should be able to inject a specially crafted test object (a mock) instead of the real thing. In your case it probably means being able to set LoggerService.Instance to a special mock object.
The second thing you need is the fake logger instance that you will test against. You probably want a mock, which is a special object that can be set up to check behaviour of the caller. There are several mock frameworks around and I really recommend that you use one instead of trying to roll your own.

Anders' answer was definitely the "canonical" way of approaching the problem, but in .NET 4.5, there's a second option:
The Fakes framework.
It lets you add a "fakes" assembly to your unit test project that accepts a delegate to perform in place of the actual implementation of a method. Here's an example using File.ReadAllText
[TestMethod]
public void Foo()
{
using (ShimsContext.Create())
{
ShimFile.ReadAllTextString = path => "test 123";
var reverser = new TextReverser();
const string expected = "321 tset";
//Act
var actual = reverser.ReverseSomeTextFromAFile(#"C:\fakefile.txt");
//Assert
Assert.AreEqual(expected, actual);
}
}
What that test method is doing is temporarily (within the scope of the ShimsContext) replacing the implementation of File.ReadAllText with the lambda I provided. In this case, any time ReadAllText is called, it returns the string "test 123".
It's slower than regular DI, but if you're absolutely tied to a specific implementation of a singleton, it could be exactly what you need. Read more about it here.

What Anders said.
Several popular mocking frameworks are Moq and RhinoMocks
And you'd change your code so that the logger dependency was injected to your class:
public class ClassWithMethodsIWantToUnitTest
{
public ClassWithMethodsIWantToUnitTest(ILoggerService logger)
{}
public void myFcn(object someArg)
{
...
logger.LogMessage("myMessage");
...
}
}
Or something similar. A DI framework could inject the logger automatically into the class when it needs it. Esentially a DI framework automatically calls
new ClassWithMethodsIWantToUnitTest(LoggerService.Instance);

Related

How to refactor to avoid using a Shim?

I'm pretty new to Unit Testing and am exploring the Microsoft Fakes framework - primarily because it's free and it allows me to mock SharePoint objects easily with the Emulators package. I've seen various mentions on SO and elsewhere that Shims are evil and I more or less understand why. What I don't get is how to avoid them in one specific case - in other words, "how should I refactor my code to avoid having to use shims?"
For the code in question, I have a JobProcessor object that has properties and methods, some of which are private as they should only be called from the public Execute method. I want to test that when Execute is called and there is a Job available that its Process method is called as I need to do some extra logging.
Here's the relevant code:
//in system under test - JobProcessor.cs
private IJob CurrentJob { get; set; }
public void Execute()
{
GetJobToProcess(); //stores Job in CurrentJob property if found
if (ShouldProcessJob){
CurrentJob.ProcessJob();
}
}
I need to do some extra things if ProcessJob is called from a test, so I set up a Stub in my Test Method to do those extra things:
StubIJob fakeJob = new StubIJob(){
ProcessJob = () =>{
//do my extra things here
}
};
I'm testing the ProcessJob method itself elsewhere so I don't care that it doesn't do anything but my extra stuff here. As I understand things, I now need to set up a Shim to have the private method GetJobsToProcess from JobProcessor (my system under test) return my fake job so that my stubbed method is called:
processor = new JobProcessor();
ShimJobProcessor.AllInstances.GetJobToProcess = (#this) =>{
var privateProcessor = new PrivateObject(processor);
privateProcessor.SetProperty("CurrentJob", fakeJob); //force my test Job to be processed so the Stub is used
};
In this case, how should I avoid using the Shim? Does it matter?
Thanks.
This is a case where rather than using a shim or stub, I'd just make the method return a boolean to notify whether or not the inner call has happened.
The problem with using fakes there is that you're assuming that some method of some object is called, which the test should not know. Tests should be dumb, and only see the outside of the code. Tests, like any other code, should not care how a value was reached, just that it is correct.
However, your code has another issue as well. You're getting some unknown object and using it within the same scope. You should remove the call to GetJobToProccess from Execute.
It's the principle of Dependency Injection: a method should not spin up and hide it's dependencies; if it depends on an object, that object should be possible to change freely or be passed in. The exact implementation of the job should not matter to the execute method, and that, along with the naming, implies that you should not be getting that object and executing it in the same call.

Do I have to fake a value object in my unit test

I have written a class using TDD containing a method (method under test) which takes a simple value object as a parameter (range).
Code:
The method under test looks like this:
public List<string> In(IRange range)
{
var result = new List<string>();
for (int i = range.From; i <= range.To; i++)
{
//...
}
return result;
}
Furthermore I have a unit test to verify my method under test:
[TestMethod]
public void In_SimpleNumbers_ReturnsNumbersAsList()
{
var range = CreateRange(1, 2);
var expected = new List<string>() { "1", "2" };
var result = fizzbuzz.In(range);
CollectionAssert.AreEqual(expected, result);
}
private IRange CreateRange(int from, int to)
{
return new Fakes.StubIRange()
{
FromGet = () => { return from; },
ToGet = () => { return to; }
};
}
Question:
I have read Roy Osherove's book on unit testing ("The Art of Unit Testing"). In there he says
"external dependencies (filesystem, time, memory etc.) should be
replaced by stubs"
What does he mean by external dependency? Is my value object (range) also an external dependency which should be faked? Should I fake all dependencies a class have?
Can someone give me an advice
TL;DR
Do the simplest thing possible that solves your problem.
The longer I have been using TDD, the more I appreciate the value of being pragmatic. Writing super-duper isolated unit tests is not a value unto itself. The tests are there to help you write high quality code that is easy to understand and solves the right problem.
Adding an interface for the range class is a good idea if you have the need to be able to switch to another concrete range implementation without having to modify the code which depends on it.
However, if you do not have that need adding an interface serves no real purpose, but it does add some complexity, which actually takes you further from the goal of writing easy to understand code which solves the problem.
Be careful not to think to much about what might change in the future. YAGNI is a good principle to follow. If you have been doing TDD you won't have any problems refactoring the code if an actual need occurs in the future, since you have solid tests to rely on.
In general terms I would not consider a proper Value Object to be a dependency. If it is complex enough that you feel uncomfortable letting other code use it when under test it sounds like it is actually more like a service.
A unit test should run in isolation (completely in memory) without having to touch any external systems, such as file system, database, web service, mail service, system clock, or anything that is either slow, hard to setup, or undeterministic (such as the ever changing system time).
To be able to do this, you should abstract away those external dependencies which allows you to mock them in your tests.
A unit test however, goes one step further. In a unit test you often only want to test the logic of a single method or a single class. You're not interested to verify how multiple components integrate, but you just want to verify that the logic of that single class is correct, and that it communicates correctly with other components.
To be able to do this, you need to fake those other components (the class's dependencies). So in general you should indeed fake all dependencies (that contain behavior) a class has.

What's the correct way to use Stubs and Mocks?

Here's my example:
[TestMethod]
public void NewAction_should_return_IndexAction()
{
NewViewModel viewModel = new NewViewModel()
{
Name = "José Inácio Santos Silva",
Email = "joseinacio#joseinacio.com",
Username = "joseinacio"
};
//IsUserRegistered is used to validate Username, Username is unique.
_mockAuthenticationService.Setup(x => x.IsUserRegistered(viewModel.Username )).Returns(false);
//IsUserRegistered is used to validate Email, Email is unique.
_mockUsuarioRepository.Setup(x => x.GetUserByEmail(viewModel.Email));
_mockDbContext.Setup(x => x.SaveChanges());
_mockUsuarioRepository.Setup(x => x.Add(It.IsAny<User>()));
_userController = new UserController(_mockUsuarioRepository.Object, _mockDbContext.Object, _mockAuthenticationService.Object);
ActionResult result = _userController.New(viewModel);
result.AssertActionRedirect().ToAction("Index");
_mockAuthenticationService.VerifyAll();
_mockUsuarioRepository.VerifyAll();
_mockDbContext.VerifyAll();
}
I have read some tutorials and they say that we should use only one mock per test.
But look at my test, it use 3 mocks, to check if my Action is working the right way I need to check these 3 mocks, do not agree?
How do I make this test in the correct way?
Each unit test should test only one thing.
In your unit test you are testing three mock objects. If the mockAuthenticationService fails, this will be reported and the unit test will stop there. Any errors with the other Mock objects are not reported and are effectively hidden.
In this situation you should create three unit tests, and in each one verify only one of the Mock objects. The rest are just used as stubs. (A stub is exactly the same as a Mock object, except you dont call VerifyAll on it at the end)
To avoid duplication and wasted effort, you should refactor that unit test so that most of the code is in a separate method. Each of the three unit tests calls this method and then verifies a single Mock.
You also have a test to ensure the correct redirect is called. This should also be in a separate test.
Quite simply:
[TestMethod]
public void NewAction_should_checkUserRegistered()
{
SetupTest();
_mockAuthenticationService.VerifyAll();
}
[TestMethod]
public void NewAction_should_GetUserByEmail()
{
SetupTest();
_mockUsuarioRepository.VerifyAll();
}
[TestMethod]
public void NewAction_should_SaveDBContext()
{
SetupTest();
_mockDbContext.VerifyAll();
}
[TestMethod]
public void NewAction_should_return_Redirects_Action()
{
var novoActionResult = SetupTest();
novoActionResult.AssertActionRedirect().ToAction("Index");
}
Short answer: "only one mock per test." is ambiguous. Use as many fakes as you need to isolate the code under test to a "unit" that is testing one condition.
It should be phrased: Only test one thing per test. If you are checking the state of more than one mock object you are probably testing more than one thing.
Long answer:
There is a lot to answer here to get the unit test written according to the best practices I have come across.
Common terminology from (The Art of Unit Testing), which I hope will come to be common:
Fake - an object that isolates the code under test from the rest of the application.
Stub - a simple fake object.
Mock - a fake object that stores what is passed to it, that you can inspect to verify the test.
Stubs and Mocks are both types of fake.
"only one mock per test." is wrong. You use as many fakes as you need to fully isolate the code under test from the rest of the application. If a method takes no parameters, there's nothing to fake. If a method takes a simple data type e.g. int, string, that doesn't have any complex behaviour, you don't need to fake it. If you have 2 repositories, context, a service object passed in, fake all of them, so no other production methods are being called.
You should have one condition per test as #Mongus Pong has said.
Test naming convention: MethodUnderTest_Condition_ExpectedBehaviour in this case you cannot do that as you have got more than one condition tested.
Test pattern: Arrange, Act, Assert. From your test, it seems as that is what you have done, but you have are arranging using private members. You should replace these with variables in each test, since the running order of tests is not always enforced, the state of these variables cannot be guaranteed, making your tests unreliable.
Buy a copy of "The Art of Unit Testing" http://artofunittesting.com/ it will answer a lot of more of your questions and is a great investment; one of the books that I'd grab if the office caught fire.
IMHO mocks and stubs are not that unique defined - every author uses them slightly different.
As I understand stubs "mock" behavior or "output" while you use mocks for example to check "input" into the mocked object/interface (like the Verify-Methods in MOQ).
If you see it this way then yes I too think you should only use one Mock because you should only test one thing - if you see it more like the stubs to inject testable interfaces then it's impossible to do.
If the VerifyAll is really needed here you indeed use 3 mocks, but I don't think they are nedded.
The best way to use Mock and stubs with Dev Magic Fake, so you can mock the UI and the DB for more information see Dev Magic Fake on codePlex
http://devmagicfake.codeplex.com/
Thanks
M.Radwan

Unit Testing - Is it bad form to have unit test calling other unit tests

I have a unit test called TestMakeAValidCall(). It tests my phone app making a valid call.
I am about to write another test called TestShowCallMessage() that needs to have a valid call made for the test. Is it bad form to just call TestMakeAValidCall() in that test?
For reference this is my TestMakeAValidCall() test.
[TestMethod]
public void TestMakeAValidCall()
{
//Arrange
phone.InCall = false;
phone.CurrentNumber = "";
// Stub the call to the database
data.Expect(x => x.GetWhiteListData()).
Return(FillTestObjects.GetSingleEntryWhiteList());
// Get some bogus data
string phoneNumber = FillTestObjects.GetSingleEntryWhiteList().
First().PhoneNumber;
// Stub th call to MakeCall() so that it looks as if a call was made.
phone.Expect(x => x.MakeCall(phoneNumber)).
WhenCalled(invocation =>
{
phone.CurrentNumber = phoneNumber;
phone.InCall = true;
});
//Act
// Select the phone number
deviceControlForm.SelectedNumber = phoneNumber;
// Press the call button to make a call.
deviceMediator.CallButtonPressed();
//Assert
Assert.IsTrue(phone.InCall);
Assert.IsTrue(phone.CurrentNumber == phoneNumber);
}
Refactor the setup to another method and call that method from both tests. Tests should not call other tests.
IMHO, you should do one of the following:
Create a method that returns a valid call, and use it separately for both tests (not one calling the other)
Mock the valid call for the ShowCallMessageTest
To offer a counter point:
I strongly believe that well designed unit test should depend on one another!
Of course, that makes sense only if the testing framework is aware of these dependencies such that it can stop running dependent test when a dependency fails. Even better, such a framework can pass the fixture from test to test, such that can build upon a growing and extending fixture instead of rebuilding it from scratch for each single test. Of course, caching is done to take care no side-effects are introduced when more than one test depends from the same example.
We implemented this idea in the JExample extension for JUnit. There is no C# port yet, though there are ports for Ruby and Smalltalk and ... the most recent release of PHPUnit picked up both our ideas: dependencies and fixture reuse.
PS: folks are also using it for Groovy.
I think its a bad idea. You want your unit test to test one thing and one thing only. Instead of creating a call through your other test, mock out a call and pass it in as an argument.
A unit test should test one unit/function of your code by definition. Having it call other unit tests makes it test more than one unit. I break it up in to individual tests.
Yes - unit tests should be separate and should aim to test only one thing (or at least a small number of closely-related things). As an aside, the calls to data.Expect and phone.Expect in your test method are creating expectations rather than stub calls, which can make your tests brittle if you refactor...
A unit vs. module....we also think tests should depend on reusable methods as well and should test at an api level testing integration of classes. Many just tests a single class but many bugs are at that integration between the class level. We also use verifydesign to guarantee the api does not depend on implementation. This allows you to refactor the whole component/module without touching a test(and we went through that once actually and it worked great). Of course, any architectural changes force you to refactor the tests but at least design changes in the module don't cause test refactor work(unless you change the behavior of the api of course implicitly like firing more events than you used to but that "would" be an api change anyways).
"Could someone ellaborate on how the refactoring would look like in this case? – Philip Bergström Nov 28 '15 at 15:33"
I am currently doing something like this and this is what i came up with:
Notice that ProcessorType and BuildProcessors both call TestLevels
the actual content besides that fact is unimportant
its using XUnit, and Shouldly NuGet package
private static void TestLevels(ArgProcessor incomingProcessor)
{
Action<ProcessorLevel, int> currentLevelIteration = null;
currentLevelIteration = (currentProcessor, currentLevel) =>
{
currentProcessor.CurrentLevel.ShouldBeEquivalentTo(currentLevel);
ProcessorLevel nextProcessor = currentProcessor.CurrentProcessor;
if (nextProcessor != null)
currentLevelIteration(nextProcessor, currentLevel + 1);
};
currentLevelIteration(incomingProcessor, 0);
}
[Theory]
[InlineData(typeof(Build), "Build")]
public void ProcessorType(Type ProcessorType, params string[] args)
{
ArgProcessor newCLI = new OriWeb_CLI.ArgProcessor(args);
IncomingArgumentsTests.TestLevels(newCLI);
newCLI.CurrentProcessor.ShouldBeOfType(ProcessorType);
}
[Theory]
[InlineData(typeof(Build.TypeScript), "TypeScript")]
[InlineData(typeof(Build.CSharp), "CSharp")]
public void BuildProcessors(Type ProcessorType, params string[] args)
{
List<string> newArgs = new List<string> {"Build"};
foreach(string arg in args) newArgs.Add(arg);
ArgProcessor newCLI = new OriWeb_CLI.ArgProcessor(newArgs.ToArray());
IncomingArgumentsTests.TestLevels(newCLI);
newCLI.CurrentProcessor.CurrentProcessor.ShouldBeOfType(ProcessorType);
}

What is use of Moq?

I keep seeing this referred to on DotNetKicks etc... Yet cannot find out exactly what it is (In English) or what it does? Could you explain what it is, or why I would use it?
Moq is a mocking framework for C#/.NET. It is used in unit testing to isolate your class under test from its dependencies and ensure that the proper methods on the dependent objects are being called. For more information on mocking you may want to look at the Wikipedia article on Mock Objects.
Other mocking frameworks (for .NET) include JustMock, TypeMock, RhinoMocks, nMock, .etc.
In simple English, Moq is a library which when you include in your project give you power to do Unit Testing in easy manner.
Why? Because one function may call another, then another and so on. But in real what is needed, just the return value from first call to proceed to next line.
Moq helps to ignore actual call of that method and instead you return what that function was returning. and verify after all lines of code has executed, what you desired is what you get or not. Too Much English, so here is an example:
String Somethod()
{
IHelper help = new IHelper();
String first = help.firstcall();
String second= secondcall(first);
return second;
}
Now, here first is needed to for secondcall(), but you can not actually call help.firstcall() as it in some other layer. So Mocking is done, faking that method was called:
[TestMethod]
public void SomeMethod_TestSecond
{
mockedIHelper.Setup(x=>x.firstcall()).Returns("Whatever i want");
}
Here, think, SetUP as faking method call, we are just interested in Returns.
Moq is a mocking engine for doing .Net TDD.

Categories

Resources