I need to some how unit test this method. The problem is that FsFileGroupFile is not easily mocked, it has complex constructor requirements and doesn't directly use an interface. _blockReaderFactory on the other hand is an interface and therefore easy to mock. How can I mock such a complicated object. I'm using Rhino Mocks and the Microsoft Unit Testing Framework. Any one have any ideas?
public void ReadGeneral(FsFileGroupFile a_file, FileItemData a_fileItemData)
{
try
{
var blockReader = _blockReaderFactory.Create(a_file.File.FullName, "CabinetData/StartData");
var version = blockReader.ReadVersion();
var name = blockReader.ReadString();
var type = blockReader.ReadString();
var defaultHeight = blockReader.ReadDouble();
var defaultWidth = blockReader.ReadDouble();
var defaultDepth = blockReader.ReadDouble();
a_fileItemData.Name = name;
a_fileItemData.DefaultWidth = defaultWidth * 100.0;
a_fileItemData.DefaultHeight = defaultHeight * 100.0;
a_fileItemData.DefaultDepth = defaultDepth * 100.0;
}
catch (Exception ex)
{
throw new IOException("General data could not be read from block data.", ex);
}
}
It seems that you're only using a_file to get the filename. So why not create an interface FilenameSupplier (or similar), and write a wrapper that implements it?
Java code example (added before question was tagged as C#...):
interface FilenameSupplier {
String getName();
}
public void ReadGeneral(FilenameSupplier a_file, FileItemData a_fileItemData) {
...
a_file.getName();
...
}
class ConcreteSupplier implements FilenameSupplier {
private final FsFileGroupFile file;
public ConcreteSupplier(FsFileGroupFile file) { this.file = file; }
String getName() { return a_file.File.FullName; }
}
You should extract some interface from FsFileGroupFile and pass it into constructor argument.
Then you can easily mock this interface with your preferable framework, Rhino Mocks in your case.
If it is not appropriate, you should build your FsFileGroupFile and may be use mocks when passing arguments in its complex constructor.
Seems that there is no another options, except may be you should review your design here. If classes are so hard to test it can be a sign of poor design.
When I have had to create complicated objects in a test I've used the Test Data Builder Pattern. As an example let's assume that you have five values to pass to the constructor:
public FsFileGroupFile(string firstProperty, string secondProperty,
string thirdProperty, string fourthProperty, string fifthProperty)
{
// constructor logic goes here
}
This would then be wrapped with a test builder class in the unit test project:
public class FsFileGroupFileBuilder
{
public string FirstProperty { get; set; }
public string SecondProperty { get; set; }
public string ThirdProperty { get; set; }
public string FourthProperty { get; set; }
public string FifthProperty { get; set; }
public FsFileGroupFile Build()
{
return new FsFileGroupFile(FirstProperty, SecondProperty, ThirdProperty,
FourthProperty, FifthProperty);
}
}
Now you can assign values to only the properties you care about and build your object in this way:
// in your test setup use this to initial to a default/valid state
var fsFileGroupBuilder = new fsFileGroupBuilder
{
FirstProperty = "Default",
SecondProperty = "Default",
ThirdProperty = "Default",
FourthProperty = "Default",
FifthProperty = "Default"
}
Note: Rhino Mocks can probably set those default value for you, but I have not used it personally so I'm not sure.
// Override the properties in each test
fsFileGroupBuilder.ThirdProperty = "Value needed for unit test."
// create
var fileItemData = new FileItemData();
ReadGeneral(fsFileGroupBuilder.Build(), fileItemData);
There are other open source libraries that can help with generating the test data such as NBuilder which have worked well for me in the past.
The main point here is that the complex constructor can be abstracted away with a builder which will allow you to concentrate on testing your business logic instead of satisfying the constructor in every test.
Related
Background
I'm fixing unit tests which have been neglected for a long time for legacy code in our organisation. They're written using Rhino Mocks 3.4.0, and I'm struggling to find a way of making this test pass. Rhino Mocks documentation seems to have gone, and most answers here and blogs seem to be using updated 3.5 and 3.6 syntax.
I'm wary of updating the version of Rhino Mocks we're using, as we have several thousand unit tests which may or may not need updated if we update.
The scenario:
We have a Presenter and a View. When the Presenter is initialised, it sets some default filter properties in the View. In the past, both of these properties were enums and the test passed.
The last change updated one of the properties to be an instance of a class. The test was updated to expect a call to a static method which creates an instance with default values (matching the code under test), but the test now fails with the error Rhino.Mocks.Exceptions.ExpectationViolationException : Unordered method call.
Some sample code:
public enum FilterOptions { OptionA, OptionB, OptionC }
public class OtherFilterOptions
{
public bool Filter1 { get; set;}
public bool Filter2 { get; set; }
public OtherFilterOptions(bool filter1 = true, bool filter2 = false)
{
Filter1 = filter1;
Filter2 = filter2;
}
public static OtherFilterOptions DefaultFilterOptions()
{
return new OtherFilterOptions();
}
}
public interface IToTestView
{
FilterOptions Property1 { set; }
OtherFilterOptions Property2 { set; }
}
public class ToTestPresenter
{
public IToTestView View { get; set; }
public ToTestPresenter(IToTestView view)
{
View = view;
}
public void InitialiseView()
{
View.Property1 = FilterOptions.OptionA;
View.Property2 = OtherFilterOptions.DefaultFilterOptions();
}
}
And a failing test:
[TestFixture]
class Tests
{
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = mocks.CreateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
using (mocks.Ordered())
{
mockView.Property1 = FilterOptions.OptionA;
mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
}
mocks.ReplayAll();
presenter.InitialiseView();
mocks.VerifyAll();
}
}
The full error is
Rhino.Mocks.Exceptions.ExpectationViolationException : Unordered method call! The expected call is: 'Ordered: { IToTestView.set_Property2(RhinoMocksTestApp.OtherFilterOptions); }' but was: 'IToTestView.set_Property2(RhinoMocksTestApp.OtherFilterOptions);'
I'm assuming that the test is failing because the value to be set is a method call rather than a concrete value. I've tried declaring a variable using mockView.Property2 = theVariable, but there's no change to the error.
Can I set an expectation that Property2 will be set to {some object with Values Filter1 = true, Filter2 = false}? I've seen examples doing similarly using Rhino Mocks 3.6, but is anything available using 3.4.0?
Edit:
As an example, this is an example test which passes in Rhino Mocks 3.6.1 - I'm hoping to find some syntax that works similarly for 3.4.0, if it exists.
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = MockRepository.GenerateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
mocks.ReplayAll();
presenter.InitialiseView();
mockView.AssertWasCalled(v => v.Property1 = FilterOptions.OptionA);
mockView.AssertWasCalled(v => v.Property2 = Arg<OtherFilterOptions>.Matches(filters =>
(filters.Filter1 == true) && (filters.Filter2 == false)));
}
The answer I was looking for was in the LastCall.Constraints() method. Passing arguments to Constraints allows you to specify property values of an argument:
[Test]
public void TestOne()
{
var mocks = new MockRepository();
var mockView = mocks.CreateMock<IToTestView>();
ToTestPresenter presenter = new ToTestPresenter(mockView);
using (mocks.Ordered())
{
mockView.Property1 = FilterOptions.OptionA;
mockView.Property2 = OtherFilterOptions.DefaultFilterOptions();
LastCall.Constraints(
Property.Value("Filter1", true)
& Property.Value("Filter2", false));
}
mocks.ReplayAll();
presenter.InitialiseView();
mocks.VerifyAll();
}
There are a large number of options that can be passed in to the Constraints() method. Details on some of them on this CodeProject page
Another option is LastCall.IgnoreArguments() if you don't care what the property is actually set to.
in a webforms application, let's say we have a class that has a method that does some job with the use of DateTime.Now, if I want to test this method I can inject a DateTimeWrapper using the constructor but in my scenario I don't want the IoC container to construct the class for me, instead I want to use it "new it" and have it testable and I think it makes no sense that each time we want to use this class, a dependency of the DateTimeWrapper "which returns the real DateTime.Now" should be injected!
Note: nothing is being injected in the WebForms page class.
public class EmailNotification
{
public IDateTimeWrapper DateTimeWrapper { get; set; }
public void SetBody(string body)
{
...
Body = body + DateTimeWrapper.Now.ToString();
}
}
I tried to use Property injection using "Autofac" and the following works perfect:
builder.RegisterType<DateTimeWrapper>()
.As<IDateTimeWrapper>();
builder.RegisterType<EmailNotification>().PropertiesAutowired();
// in this case, it works
var email = container.Resolve<EmailNotification>();
email.SetBody("hello world!");
But I need to use the component like this:
// somehow I want the DateTimeProvider "the real one" to be injected or used at this point
var email= new EmailNotification();
email.SetBody("hello world!");
// I'm getting a NullReferenceException at the last line because the dependency has been never injected
do you have an idea?
thanks in advance
the solution was simple "i think", I changed this:
public class EmailNotification
{
public IDateTimeWrapper DateTimeWrapper { get; set; }
public void SetBody(string body)
{
...
Body = body + DateTimeWrapper.Now.ToString();
}
}
to the following:
public class EmailNotification
{
private IDateTimeWrapper _dateTimeWrapper = new DateTimeWrapper();
public IDateTimeWrapper DateTimeWrapper
{
get
{
return _dateTimeWrapper;
}
set
{
_dateTimeWrapper = value ?? throw new ArgumentNullException(nameof(DateTimeWrapper));
}
}
public void SetBody(string body)
{
...
Body = body + DateTimeWrapper.Now.ToString();
}
}
so I still have IDateTimeWrapper as a seam for unit testing and at the same time it gets initialized by default when constructing an instance of the EmailNotification class.
I have a class that needs to get some data to perform analysis. Let's say the interface for getting the data is as follows:
public interface IDataFetcher
{
List<someobject> GetData();
}
In a very simple case my class will use this interface as follows in one of its methods:
void PerformAnalysis(List<IDataFetcher> fetchers)
{
...
foreach(IDataFetcher fetcher in fetchers)
{
List<someobject> myList = fetcher.GetData();
//We will try fetching one by one using different fetchers until we get the data
if(myList.Count > 0)
break;
}
...
}
Now, different fetching implementations such as fetching from file, fetching from machine or fetching from dB take different input for their data sources e.g. File Fetcher would need the file path, machine fetcher would need machine name and dB fetcher would need database string.
In my case this source information can only be known at runtime (from user input or some other source) later in PerformAnalysis Method above. So, now I cannot pass IDataFetchers since source is not known.
The way I modified this was to not perform the instantiation from outside but to defer it by creating an Abstract factory as follows:
public interface IDataFetcherAbstractFactory
{
IDataFetcher CreateFetcher(string source);
}
public interface FileDataFetcherFactory : IDataFetcherAbstractFactory
{
IDataFetcher CreateFetcher(string source)
{
return new FileDataFetcher(source);
}
}
Similary, different fetchers would do the same like MachineDataFetcherFactory etc.
One implementation of a FileDataFetcher could be swapped with another by updating few tags in Unity Container XML configuration without modifying source code at all. So, this is good.
Now, I updated my method as follows:
void PerformAnalysis (List<IDataFetcherAbstractFactory> fetcherFactories)
{
...
string source = GetSource(); //source known dynamically
foreach(IDataFetcherAbstractFactory factory in fetcherFactories)
{
IDataFetcher fetcher = factory.Create(source);
List<someobject> myList = fetcher.GetData();
//We will try fetching one by one using different fetchers until we get the data
if(myList.Count > 0)
break;
}
...
}
a) Is this approach of using Factory correct or is there a better way to do this ?
b) The second issue I observed is for each factory product the source string could be different. i.e. for database factory source string is connection string, for machine its machine name etc. This means my class must be aware of what factory it is dealing with. Is it okay to make it aware ?
c) Without updating the source can a new factory be somehow passed/injected into the fectcherFactories list using unity ?
Example, someone implemented a new WebServiceFetcher : IDataFetcher and a corresponding factory for it. Now, to make my framework utilize it, I will have to modify source code to add it to the list of fetcherFactories. This does not sound scalable.
Thanks
Maybe I am missunderstanding something in your question but I will try to offer an answer:
Declare runtime data for user input values:
public interface IRuntimeData
{
string filePath { get; set; }
string connectionString { get; set; }
string machineName { get; set; }
}
class RuntimeData : IRuntimeData
{
public string filePath { get; set; }
public string connectionString { get; set; }
public string machineName { get; set; }
}
Declare interface for data fetcher and implementations. Theese classes need IRuntimeData to work.
interface IDataFetcher
{
object getData();
}
class FileFetcher : IDataFetcher
{
private string _filePath;
public FileFetcher(IRuntimeData userInputData)
{
_filePath = userInputData.filePath;
}
public object getData()
{
return "Hello from FileFetcher. File path is " + _filePath;
}
}
class DBFetcher : IDataFetcher
{
private string _connStr;
public DBFetcher(IRuntimeData userInputData)
{
_connStr = userInputData.connectionString;
}
public object getData()
{
return "Hello from DBFetcher. Connection string is " + _connStr;
}
}
class MachineFetcher : IDataFetcher
{
private string _machineName;
public MachineFetcher(IRuntimeData userInputData)
{
_machineName = userInputData.machineName;
}
public object getData()
{
return "Hello from MachineFetcher. Machine name is " + _machineName;
}
}
Declare Analyzer class. This class need a list of IDataFetcher.
class Analyzer
{
private List<IDataFetcher> _fetcherList;
public Analyzer(IDataFetcher[] fetcherList)
{
_fetcherList = new List<IDataFetcher>(fetcherList);
}
public void PerformAnalysis()
{
foreach (IDataFetcher dtFetcher in _fetcherList)
{
Console.WriteLine(dtFetcher.getData());
}
}
}
Now, register Datafetchers in the container at app bootstrap.
IUnityContainer container = new UnityContainer();
container.RegisterType<IDataFetcher, FileFetcher>("file");
container.RegisterType<IDataFetcher, DBFetcher>("db");
container.RegisterType<IDataFetcher, MachineFetcher>("machine");
When user insert runtime data, create a instance and register it in the container:
IRuntimeData rtData = new RuntimeData();
rtData.connectionString = "Persist Security Info=False;Integrated Security=true;Initial Catalog=Northwind;server=(local)";
rtData.filePath = #"C:\foo.txt";
rtData.machineName = "jlvaqueroMachine";
container.RegisterInstance<IRuntimeData>(rtData);
The last part is resolve the Analyzer through container:
Analyzer myAnalyzer = container.Resolve<Analyzer>();
myAnalyzer.PerformAnalysis();
Console.Read();
And you can see how all DataFetcher registered in the container are created an injected into Analyzer.
Full example here.
PD: If RegisterInstance of runTimeData looks like service locator anti-pattern to you; it is possible to resolve Analyzer overriding runtimeData pependency:
IRuntimeData rtData = new RuntimeData();
rtData.connectionString = "Persist Security Info=False;Integrated Security=true;Initial Catalog=Northwind;server=(local)";
rtData.filePath = #"C:\foo.txt";
rtData.machineName = "jlvaqueroMachine";
Analyzer myAnalyzer = container.Resolve<Analyzer>(new DependencyOverride<IRuntimeData>(rtData));
I have two classes that implement an interface, but both classes have a parameter passed into the constructor to identify what class the application would need. I am trying to test one (GetAvailablity) method on (AvailablityRepoData) class when I create an instance of AvailablityRepoData I am getting an error for non-virtual method. I would really appreciate if someone can point me to the right direction.
public interface IAvailablityRepo
{
string GetAvailablity(Availablity availablity);
}
public class AvailablityRepoData: IAvailablityRepo
{
public AvailablityRepoData(string websetting) {
}
public string GetAvailablity(Availablity availablity) {
return "Data";
}
}
public class AvailablityRepoWeb:IAvailablityRepo
{
public AvailablityRepoWeb(string DataSetting) {
}
public string GetAvailablity(Availablity availablity) {
return "Web";
}
}
public class Availablity
{
public virtual string Id {
get;
set;
}
public virtual string Status {
get;
set;
}
}
var a = new Availablity() { Id = "111", Status = "A"};
Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
Mock<IAvailablityRepo> RepoData = new Mock<IAvailablityRepo>();
RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity> ())).Returns("pass");
var result = RepoData.Object.GetAvailablity(a);
As has already been said in the comments, it's not clear from the code you've posted what your error is. If I copy and past it straight into visual studio (wrapping the test code in a test), the test passes fine. I'm going to suggest that when you experienced the error, you test code was actually closer to this:
[TestMethod]
public void TestMethod1() {
var a = new Availablity() { Id = "111", Status = "A" };
Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
Mock<AvailablityRepoData> RepoData = new Mock<AvailablityRepoData>();
RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity>())).Returns("pass");
var result = RepoData.Object.GetAvailablity(a);
}
This results in an error when the test is run:
System.NotSupportedException:Invalid setup on a non-virtual (overridable in VB) member:
x => x.GetAvailablity(It.IsAny<Availablity>())
The difference between this test and your original test is that I've changed the Mocked type from the interface IAvailabilityRepo to AvailabilityRepoData which is the concrete class. Since Moq only supports mocking of interfaces / virtual methods it's naturally getting upset.
As has been mentioned by #prgmtc, your test as it stands doesn't really testing much of anything.
With your current code, it doesn't actually look like you need to be using Mocks at all. Something like this might be a more appropriate test:
[TestMethod]
public void TestDataRepoReturnsDataAvailability() {
var someImportantSetting = "thisShouldBeSomethingMeaningful";
var availability = new Availablity() { Id = "111", Status = "A" };
var sut = new AvailablityRepoData(someImportantSetting);
var returnedAvailability = sut.GetAvailablity(availability);
Assert.AreEqual("Data", returnedAvailability);
}
Assuming your actual code is more complex the string passed into your data repo would presumably need to be rather more meaningful...
As a general rule of thumb, you shouldn't be mocking the system under test. If you find yourself creating a mock for the system you're testing it's a good indication that you've got to much functionality in one class and/or you're trying to test the wrong thing...
As an asside, you may want to look into something like the builder pattern to create your different repos rather than passing the type into the constructor for each of the repos as you seem to be suggesting.
I want to Unit test the method ExecLogin() using NUnit testing framework. But I'm having problem while writing code for the testing because the GenerateInput() method is declared as internal virtual. So, I'm not being able pass the SessionUserId parameter to it which I think is needed. Please guide me how to write the unit test code for ExecLogin(). I'm new to testing.
This is related to ASP.NET MVC3 testing controller actions.
public class BaseController : Controller
{
public string SessionUserId
{
get { return Session["UserId"] as string; }
set { Session["UserId"] = value; }
}
internal virtual SomeType GenerateInput(SomeType inputData)
{
var finalInput = new StringBuilder(600);
finalInput.Append("<Root>")
.Append("<UserId>")
.Append(SessionUserId)
.Append("</UserId>")
.Append("<IPAddress>")
.Append(this.GetClientIpAddress())
.Append("</IPAddress>")
.Append(inputData.InputValue)
.Append("</Root>");
inputData.InputValue = finalInput.ToString();
return inputData;
}
}
public class LoginController : BaseController
{
[HttpPost]
public JsonResult ExecLogin(JsonRequest<LoginModel> request)
{
var loginObj = request.InputObject;
var login = new StringBuilder(300);
login.Append("<UserName>").Append(loginObj.UserName).Append("</UserName>")
.Append("<Password>").Append(EncodingHelper.GetHashedPassword(loginObj.Password)).Append("</Password>")
.Append("<RememberMe>").Append(loginObj.RememberMe).Append("</RememberMe>")
;
var input = new SomeType { Operation = request.Operation, PageName = ActionName, InputValue = login.ToString() };
var returnValue = SomeDelegate.Instance.ExecuteOperation(GenerateInput(input));
return Json(new JsonResponse<string> { Status = returnValue.Status, Result = this.PopulateSession(returnValue) });
}
}
This is our model classes:
public class LoginModel
{
public string UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
public bool IsValidUser { get; set; }
}
public class JsonRequest<T>
where T : class
{
public string Operation { get; set; }
public T InputObject { get; set; }
}
While learning Dependency Injection pattern I came to know that use of concrete classes makes code more tightly coupled. And the more tightly coupled the code the harder it becomes to test. Is this why I'm not being able to test it properly? Please help.
This is actually part of a common pattern, how to provide additional hook points for testing without disturbing the interface that is publicly available, and fortunately internal is your friend here.
I assume the problem is that you have 2 assemblies, let's call them MyCode.dll and MyCode.Tests.dll for simplicity. This means that MyCode.Tests cannot access the internal methods of MyCode because, well basically it isnt internal :-)
If you go to your AssemblyInfo.cs file for your MyCode project, you can add the following
[assembly:InternalsVisibleTo("MyCode.Tests")
This does exactly what it says, it makes your internals visible inside the MyCode.Tests code base. For more info see InternalsVisibleTo and Friend assemblies