How write stub method with NUnit in C# - c#

I have 2 classes:
FirstDeep.cs
SecondDeep.cs
I did simple code for example:
class FirstDeep
{
public FirstDeep() { }
public string AddA(string str)
{
SecondDeep sd = new SecondDeep();
bool flag = sd.SomethingToDo(str);
if (flag == true)
str = string.Concat(str, "AAA");
else
str = string.Concat(str, "BBB");
return str;
}
}
and
class SecondDeep
{
public bool SomethingToDo(string str)
{
bool flag = false;
if (str.Length < 10)
{
//todo something in DB, and after that flag should be TRUE
}
return flag;
}
}
Then I want to write unit test for method "AddA":
class Tests
{
[Test]
public void AddATest()
{
string expected = "ABCAAA";
FirstDeep fd = new FirstDeep();
string res = fd.AddA("ABC");
Assert.AreEqual(expected, res);
}
}
And after that I have trouble, I don't know how correct write stub for method SomethingToDo in my Test class. I always have false. I should just return TRUE. But how?

A good way to allow you to write stubs is to use dependency injection. FirstDeep depends on SecondDeep and in your test you want to replace SecondDeep with a stub.
First change your existing code by extracting an interface for SecondDeep and then inject that into FirstDeep in the constructor:
interface ISecondDeep {
Boolean SomethingToDo(String str);
}
class SecondDeep : ISecondDeep { ... }
class FirstDeep {
readonly ISecondDeep secondDeep;
public FirstDeep(ISecondDeep secondDeep) {
this.secondDeep = secondDeep;
}
public String AddA(String str) {
var flag = this.secondDeep.SomethingToDo(str);
...
}
}
Note that FirstDeep no longer creates a SecondDeep instance. Instead an instance is injected in the constructor.
In your test you can create a stub for ISecondDeep where SomethingToDo always returns true:
class SecondDeepStub : ISecondDeep {
public Boolean SomethingToDo(String str) {
return true;
}
}
In the test you use the stub:
var firstDeep = new FirstDeep(new SecondDeepStub());
In production code you use the "real" SecondDeep:
var firstDeep = new FirstDeep(new SecondDeep());
Using a dependency injection container and a stubbing framework can make a lot of this easier to do.
If you don't want to rewrite your code you can use a framework for intercepting calls like Microsoft Moles. In the next version of Visual Studio a similar technology will be available in the Fakes Framework.

To make your code testable, do not instantiate dependencies inside your class. Use dependency injection (via constructor, property or parameter). Also use abstract classes or interfaces to allow mocking of dependencies:
class FirstDeep
{
private ISecondDeep oa;
public FirstDeep(ISecondDeep oa)
{
this.oa = oa;
}
public string AddA(string str)
{
return String.Concat(str, oa.SomethingToDo(str) ? "AAA" : "BBB");
}
}
Depending on abstractions allows you to test your class in isolation.
interface ISecondDeep
{
bool SomethingToDo(string str);
}
class SecondDeep : ISecondDeep
{
public bool SomethingToDo(string str)
{
bool flag = false;
if (str.Length < 10)
{
// without abstraction your test will require database
}
return flag;
}
}
Here is test sample (using Moq). It shows you how you can return true from call to your mocked dependency:
[TestFixture]
class Tests
{
[Test]
public void AddAAATest()
{
// Arrange
Mock<ISecondDeep> secondDeep = new Mock<ISecondDeep>();
secondDeep.Setup(x => x.SomethingToDo(It.IsAny<string>())).Returns(true);
// Act
FirstDeep fd = new FirstDeep(secondDeep.Object);
// Assert
Assert.That(fd.AddA("ABD"), Is.EqualTo("ABCAAA"));
}
}

Related

How to mock methods to return dummy data from them in C#?

I have a class that I am trying to test out through writing some unit test in C#. I am also using Moq library in my unit test for mocking.
Below are some of the methods in my class which I want to mock so that they can return some dummy data which I want to return always.
public class DataManager
{
public DataManager(ILoggingService loggingService, IConfiguration configuration)
{
// ...
}
// how to mock this to return dummy data?
private DataHolder GetData()
{
//... return DataHolder object
}
// how to mock this to return dummy data?
private IEnumerable<ProcessClient> GetClientValues(string value)
{
//... return IEnumerable<ProcessClient> object
}
}
This is how I am testing it out:
private Mock<ClientUtility> utility;
[SetUp]
public void Setup()
{
utility = new Mock<ClientUtility>();
}
[Test]
public void Test1()
{
// what should I do here so that "GetData" and "GetClientValues" return dummy data when I call below class constructor?
var testName = "config1";
var testContent = "{}";
utility.Setup(x => x.Add(new DataStatus { Pin = "test" }, "data.com", "test")).Returns(Task.FromResult(true));
var dataManager = new DataManager(loggingService.Object, configuration.Object);
Assert.AreEqual(testContent, dataManager.GetStuff(testName)[0]);
}
Question:
How can I mock "GetData" and "GetClientValues" using Moq or any other library to return dummy data from those two methods? Is this possible to do?
I think you can use CallBase = true.
So your mock will behave like true class.
var dataManager = new Mock<DataManager>(loggingService.Object, configuration.Object) { CallBase = true };
dataManager.Object.Method1();
dataManager.Object.Method2();
And you can mock some methods like you do with utility.
Search by "CallBase" on page:
https://github.com/Moq/moq4/wiki/Quickstart
UPDATE
I made methods public to call them.
And there is some issue, that i didn't see last time. You need to make "virtual" methods if you want change their behavior.
There is example of code. As you can see, GetClientValues() returns real data because we call default real implementation with CallBase = true and GetData() returns dummy data because we mocked its behavior.
public class DataManager
{
public DataManager(ILoggingService loggingService, IConfiguration configuration)
{
// ...
}
// how to mock this to return dummy data?
public virtual DataHolder GetData()
{
return new DataHolder
{
Data = "RealData"
};
}
// how to mock this to return dummy data?
public IEnumerable<ProcessClient> GetClientValues(string value)
{
return new List<ProcessClient>
{
new ProcessClient
{
Data = "RealData"
}
};
}
}
And tests.
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
var loggingService = new Mock<ILoggingService>();
var config = new Mock<IConfiguration>();
var dataManager = new Mock<DataManager>(loggingService.Object, config.Object){CallBase = true};
dataManager.Setup(x => x.GetData()).Returns(new DataHolder { Data = "FakeData" });
Assert.AreEqual("RealData", dataManager.Object.GetClientValues("test").First().Data);
Assert.AreEqual("FakeData", dataManager.Object.GetData().Data);
}
}
But anyway i think, that this approach isn't good for testing.
There is a problem with testing private methods. We have some ways (for example Invoke()), but in general, "if you want to unit test a private method, something may be wrong". I would like to recommend you to read something about test design and writing testable code.
About testing private methods How do you unit test private methods?.

Mocking an object initialised inside a method under test

I am trying to test a class which instatiates another class within it. It is the instatinated class call I want to mock.
Is this possible or is they a way around it/ simpler way I am missing?
Below I have written up a simpler example which still has the same problemts as my main code.
public interface my_interface
{
int returns_25();
}
public class class_i_want_to_mock : my_interface
{
public int returns_25()
{
// TEST SHOULD FAIL SO NEED MOCK TO PASS THE CASE
return 7645745;
}
}
In another namespace (it has access):
public class class_to_test
{
public static int returns_25()
{
class_i_want_to_mock _tempClass= new class_i_want_to_mock ();
// Will return 7645745 unless moq changes return value
int _temp_int = _tempClass.returns_25()
return _temp_int;
}
}
My test (which fails):
[Test]
public void test_returns_25()
{
// Mock
Mock<my_interface> myMock = new Mock<my_interface>();
myMock.Setup(m => m.returns_25()).Returns(25);
// Act
int return_number = class_to_test.returns_25();
// Assert
Assert.AreEqual(25, return_number);
}
Here is working code thanks to the injection idea from JSteward above.
Code is in same order
public interface my_interface
{
int returns_25();
}
public class class_i_want_to_mock : my_interface
{
public int returns_25()
{
// TEST SHOULD FAIL SO NEED MOCK TO PASS THE CASE
return 7645745;
}
}
Next class, notice the injection of the interface
public class class_to_test
{
public static int returns_25(my_interface _temp_interface)
{
// Will return 7645745 unless moq changes return value
int _temp_int = _temp_interface.returns_25()
return _temp_int;
}
}
And the test. Note the object of the Mock class has to be used (myMock.Object)
[Test]
public void test_returns_25()
{
// Mock
Mock<my_interface> myMock = new Mock<my_interface>();
myMock.Setup(m => m.returns_25()).Returns(25);
// Act
int return_number = class_to_test.returns_25(myMock.Object);
// Assert
Assert.AreEqual(25, return_number);
}

N Unit Test Debugger not stepping inside a static method

My unit testing method is as follows
[Test]
public void TrackPublicationChangesOnCDSTest()
{
//Arrange
// objDiskDeliveryBO = new DiskDeliveryBO();
//Act
var actualResult = objDiskDeliveryBO.TrackPublicationChangesOnCDS();
//Assert
var expectedZipName = 0;
Assert.AreEqual(expectedZipName, actualResult);
}
The Actual method TrackPublicationChangesOnCDS in BO is as follows
public int TrackPublicationChangesOnCDS()
{
var resultFlag = -1;
try
{
string pubUpdateFileCDSPath = CommonCalls.PubUpdateFileCDSPath;
string pubUpdateFileLocalPath = CommonCalls.PubUpdateFileLocalPath;
if (File.Exists(pubUpdateFileCDSPath))
File.Copy(pubUpdateFileCDSPath, pubUpdateFileLocalPath, true);
if (File.Exists(pubUpdateFileLocalPath))
{
string[] pubRecords = File.ReadAllLines(pubUpdateFileLocalPath);
var pubRecordsExceptToday = pubRecords.Where(p => !p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();
resultFlag = new DiskDeliveryDAO().TrackPublicationChangesOnCDS(pubRecordsExceptToday);
File.WriteAllText(pubUpdateFileLocalPath, string.Empty);
string[] pubRecordsCDS = File.ReadAllLines(pubUpdateFileCDSPath);
var pubRecordsTodayCDS = pubRecordsCDS.Where(p => p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();
File.WriteAllLines(pubUpdateFileCDSPath, pubRecordsTodayCDS);
}
return resultFlag;
}
catch (Exception)
{
return -1;
}
}
While debugging Debugger comes till
string pubUpdateFileCDSPath = CommonCalls.PubUpdateFileCDSPath;
But CommonCalls.PubUpdateFileCDSPath; return empty string . It should return a file path . when the method is called directly it works fine . It doesn't work when it is called inside a unit testing method.
CommonCalls.PubUpdateFileCDSPath is a static property defined as below .
public static string PubUpdateFileCDSPath
{
get { return GetXmlConfigValue("PubUpdateFileCDSPath"); }
}
public static string GetXmlConfigValue(string nodeName)
{
var xml = new XmlDocument();
xml.Load(ConfigValuesXml);
var node = xml.SelectSingleNode("JanesOfflineDeliveryService/" + nodeName);
return node != null ? node.InnerText : string.Empty;
}
Configvaluesxml is a xml file path . Contents of the file is
<JanesOfflineDeliveryService>
<PubUpdateFileCDSPath>D:\OfflineDelivery\CDS\pub_update.txt</PubUpdateFileCDSPath>
<PubUpdateFileLocalPath>D:\pub_update.txt</PubUpdateFileLocalPath>
</JanesOfflineDeliveryService>
In your test scenario GetXmlConfigValue("PubUpdateFileCDSPath") does not exist, so string empty is returned. Thats why you should avoid static methods, because they are not mockable. A workaround could be to pass the path variables into the method.
Using static dependencies make unit testing code in isolation difficult. invert the dependency by abstracting and injecting them into the dependent class.
public interface ICommonCalls {
string PubUpdateFileCDSPath { get; }
string PubUpdateFileLocalPath { get; }
}
the implementation of the above interface would either wrap the your static calls or better yet just implement them.
The dependent class would be refactored to allow for the dependency inversion.
public class DiskDeliveryBO {
private readonly ICommonCalls CommonCalls;
public DiskDeliveryBO(ICommonCalls common) {
this.CommonCalls = common;
}
//...other code removed for brevity.
}
However the target method also has a lot of tight coupling to implementation concerns like the file system. That too should be abstracted and inverted out of the dependent class.

unit test on a static function that read a file

I have the followed function and trying to add Unit Test on a old project. I'm a beginner in Unit Test so forgive me if the question is stupid ...
public static string GetDefaultName(bool isResponsive)
{
//Read web.config file
Configuration configuration = WebConfigurationManager.OpenWebConfiguration(System.Web.HttpContext.Current.Request.ApplicationPath);
if (!isResponsive)
{
if (configuration.AppSettings.Settings.AllKeys.Contains("defaultTheme"))
{
return configuration.AppSettings.Settings["defaultTheme"].Value;
}
else
return "default";
}
else
{
// ...
}
}
And I'm trying to write an Unit Test in this way :
[TestMethod]
public void ReturnDefaulThemeNametIfThemeIsResponsive()
{
var theme = new Theme {isResponsive = true};
var defaultName = Themes.GetDefaultName(theme.isResponsive);
Assert.AreEqual(defaultName, "defaultThemeResponsive");
}
I wonder what is the best way to test this static function, and how to mock the part who read the web.config file ?
I try to stay away from static utilities that have dependencies as they are difficult to unit test. But in this case it is possible. You will have to do some refactoring.
First you need to abstract all calls to access configuration.
public interface IThemeSettings {
bool Contains(string key);
string this[string key] { get; }
}
You can then update the static Themes utility class to use this abstraction as a dependency
public static class Themes {
private static IThemeSettings themes;
public static void Configure(Func<IThemeSettings> factory) {
if (factory == null) throw new InvalidOperationException("Must provide a valid factory method");
themes = factory();
}
public static string GetDefaultName(bool isResponsive) {
if (themes == null) throw new InvalidOperationException("Themes has not been configured.");
string result = string.Empty;
if (!isResponsive) {
if (themes.Contains("defaultTheme")) {
result = themes["defaultTheme"];
} else
result = "default";
} else {
// ...
}
return result;
}
//...
}
That wat you can now configure the utility to use mocks when testing
[TestMethod]
public void ReturnDefaulThemeNametIfThemeIsResponsive() {
//Arrange
var key = "defaultTheme";
var expected = "defaultThemeResponsive";
var mockSettings = new Mock<IThemeSettings>();
mockSettings.Setup(m => m.Contains(key)).Returns(true);
mockSettings.Setup(m => m[key]).Returns(expected);
//In production you would also do something like this with
//the actual production implementation, not a mock
Themes.Configure(() => mockSettings.Object);
var theme = new Theme { isResponsive = true };
//Act
var defaultName = Themes.GetDefaultName(theme.isResponsive);
//Assert
Assert.AreEqual(expected, defaultName);
}
In this case I used Moq as the mocking framework.
Some advice. Try not to have your classes tightly coupled to HttpContext. Your classes should depend on abstractions and not on concretions.
The way your method is designed at the moment does not allow you to mock the part that reads the config file. If you want to be able to do that you need to make it a parameter to your method. One way to make that easier is to define an interface like
public interface ISetting
{
string GetConfigItem(string itemName);
}
Then wrap the Configuration object in a settings manager class that implements this.
public class MySettings:ISetting
{
public string GetConfigItem(string ItemName)
{
// return value of the setting. In your case code that gets value of "defaultTheme"
}
}
Your method will now have a dependency on ISetting.
For testing purposes you can create a mock that implements the interface and will return what ever value you want independent of the current state and content of the web.config
public class SettingsTestHelper:ISetting
{
private _valueToReturn;
public SettingsTestHelper(string valueToReturn)
{
_valueToReturn=valueToReturn;
}
public string GetConfigItem(string itemName)
{
return valueToReturn;
}
}
With this you can now create a unit test(doesn't compile, but you'll get the idea)
[TestMethod]
public void CanGetSetting()
{
var helper = new SettingsTestHelper("default");
var result = ClasThatImplementsYourStaticMethod.GetDefaultName(helper, true);
Assert.AreEqual(expected, actual);
}

Test Environment.Exit() in C#

Is there in C# some kind of equivalent of ExpectedSystemExit in Java? I have an exit in my code and would really like to be able to test it. The only thing I found in C# is a not really nice workaround.
Example Code
public void CheckRights()
{
if(!service.UserHasRights())
{
Environment.Exit(1);
}
}
Test Code
[TestMethod]
public void TestCheckRightsWithoutRights()
{
MyService service = ...
service.UserHasRights().Returns(false);
???
}
I am using the VS framework for testing (+ NSubstitute for mocking) but it is not a problem to switch to nunit or whatever for this test.
You should use dependency injection to supply to the class being tested an interface that provides an environmental exit.
For example:
public interface IEnvironment
{
void Exit(int code);
}
Let's also assume that you have an interface for calling UserHasRights():
public interface IRightsService
{
bool UserHasRights();
}
Now suppose your class to be tested looks like this:
public sealed class RightsChecker
{
readonly IRightsService service;
readonly IEnvironment environment;
public RightsChecker(IRightsService service, IEnvironment environment)
{
this.service = service;
this.environment = environment;
}
public void CheckRights()
{
if (!service.UserHasRights())
{
environment.Exit(1);
}
}
}
Now you can use a mocking framework to check that IEnvironment .Exit() is called under the right conditions. For example, using Moq it might look a bit like this:
[TestMethod]
public static void CheckRights_exits_program_when_user_has_no_rights()
{
var rightsService = new Mock<IRightsService>();
rightsService.Setup(foo => foo.UserHasRights()).Returns(false);
var enviromnent = new Mock<IEnvironment>();
var rightsChecker = new RightsChecker(rightsService.Object, enviromnent.Object);
rightsChecker.CheckRights();
enviromnent.Verify(foo => foo.Exit(1));
}
Ambient contexts and cross-cutting concerns
A method such as Environment.Exit() could be considered to be a cross-cutting concern, and you might well want to avoid passing around an interface for it because you can end up with an explosion of additional constructor parameters. (Note: The canonical example of a cross cutting concern is DateTime.Now.)
To address this issue, you can introduce an "Ambient context" - a pattern which allows you to use a static method while still retaining the ability to unit test calls to it. Of course, such things should be used sparingly and only for true cross-cutting concerns.
For example, you could introduce an ambient context for Environment like so:
public abstract class EnvironmentControl
{
public static EnvironmentControl Current
{
get
{
return _current;
}
set
{
if (value == null)
throw new ArgumentNullException(nameof(value));
_current = value;
}
}
public abstract void Exit(int value);
public static void ResetToDefault()
{
_current = DefaultEnvironmentControl.Instance;
}
static EnvironmentControl _current = DefaultEnvironmentControl.Instance;
}
public class DefaultEnvironmentControl : EnvironmentControl
{
public override void Exit(int value)
{
Environment.Exit(value);
}
public static DefaultEnvironmentControl Instance => _instance.Value;
static readonly Lazy<DefaultEnvironmentControl> _instance = new Lazy<DefaultEnvironmentControl>(() => new DefaultEnvironmentControl());
}
Normal code just calls EnvironmentControl.Current.Exit(). With this change, the IEnvironment parameter disappears from the RightsChecker class:
public sealed class RightsChecker
{
readonly IRightsService service;
public RightsChecker(IRightsService service)
{
this.service = service;
}
public void CheckRights()
{
if (!service.UserHasRights())
{
EnvironmentControl.Current.Exit(1);
}
}
}
But we still retain the ability to unit-test that it has been called:
public static void CheckRights_exits_program_when_user_has_no_rights()
{
var rightsService = new Mock<IRightsService>();
rightsService.Setup(foo => foo.UserHasRights()).Returns(false);
var enviromnent = new Mock<EnvironmentControl>();
EnvironmentControl.Current = enviromnent.Object;
try
{
var rightsChecker = new RightsChecker(rightsService.Object);
rightsChecker.CheckRights();
enviromnent.Verify(foo => foo.Exit(1));
}
finally
{
EnvironmentControl.ResetToDefault();
}
}
For more information about ambient contexts, see here.
I ended up creating a new method which I can then mock in my tests.
Code
public void CheckRights()
{
if(!service.UserHasRights())
{
Environment.Exit(1);
}
}
internal virtual void Exit()
{
Environment.Exit(1);
}
Unit test
[TestMethod]
public void TestCheckRightsWithoutRights()
{
MyService service = ...
service.When(svc => svc.Exit()).DoNotCallBase();
...
service.CheckRights();
service.Received(1).Exit();
}
If your goal is to avoid extra classes/interfaces just to support tests, how do you feel about Environment.Exit action via Property Injection?
class RightsChecker
{
public Action AccessDeniedAction { get; set; }
public RightsChecker(...)
{
...
AccessDeniedAction = () => Environment.Exit();
}
}
[Test]
public TestCheckRightsWithoutRights()
{
...
bool wasAccessDeniedActionExecuted = false;
rightsChecker.AccessDeniedAction = () => { wasAccessDeniedActionExecuted = true; }
...
Assert.That(wasAccessDeniedActionExecuted , Is.True);
}

Categories

Resources