How to mock constructor in c# xUnit test case? - c#

Hi I am working on C# application. I am writing unit test case for controller level. Below is my controller code.
public IActionResult TriggerProductEventCheck([FromQuery(Name = "timeout-secs")] int timeoutS = 120)
{
int productEventsCount = 0;
if (productService.ProcessingEnabled)
{
var cts = new CancellationTokenSource();
cts.CancelAfter(timeoutS * 1000);
lock (SyncObject)
{
this.consumerClient.Subscribe(this.productEventTopicName);
while (!cts.IsCancellationRequested)
{
var productEvent = this.eventDispatcher.Consume();
long kafkaOffSet = productEvent.Offset.Value;
Product product = new Product(productEvent, log);
if (product.Options == null)
{
break;
}
if (product != null)
{
productService.ProcessProductEvents(product, kafkaOffSet);
}
productEventsCount++;
}
}
}
Below is my unit test case.
public void ShouldReturnIfNoSQSEvents()
{
var productEventController = MockProvider.Target<ProductEventController>();
productEventController.GetDependency<IProductEventService>().ProcessingEnabled.Returns(true);
productEventController.GetDependency<IEventDispatcher>().Consume().Returns(new Confluent.Kafka.ConsumeResult<string, Avro.Generic.GenericRecord>());
productEventController.GetDependency<IConsumerClient>().Subscribe("test");
var productclass = Substitute.For<Product>();
var response = productEventController.Target.TriggerProductEventCheck() as JsonResult;
((int)response.StatusCode).ShouldBe(200);
}
Whenever I run above unit test case, Control goes inside Product product = new Product(productEvent, log); I want to mock this particular line. May I know how to handle this condition? Any help would be appreciated. Thanks

There are at least two ways.
The most advisable: add a second method that allows you to inject the desired elements. You can call one method from the other to reuse code. This second method would be used for testing. The other shuld be left as is.
Another option is to use a framework that allows to implement shims for testing. For example:
- Moles, that "allows to replace any .NET method with a delegate". Here you can see an example that allows to mock DateTime constructor: Nikolai Tillmann: Moles - Replace any .NET method with a delegate.
- "Microsot fakes": Isolating Code Under Test with Microsoft Fakes.
- There are some commercial testing frameworks that also support shims.
However, you should use the first proposed solution, or change the desing of your software, for example using Dependency Injection, so that you can easily control de dependencies in your unit testing. You should leave the use of shims for cases where you don't have any other option, for example injecting changes in third party libraries for which you don't have the option to modify their code.
You can google ".NET shims testing" to learn more about this technique.

Related

How to mock method with FilterExpression input parameter?

I’m trying to mock method using Moq that takes FilterExpression as an input parameter and I have no luck so far. When I run it is always returns null. If I pass NULL instead of FilterExpression it works.
Here is my code:
Repository
public interface ITestRepository
{
string Test(int id, FilterExpression fe);
}
public class TestRepository : ITestRepository
{
public stringTest(int id, FilterExpression fe)
{
throw new NotImplementedException();
}
}
Unit Test
var testMock = new Mock<ITestRepository>();
var fe = new FilterExpression();
var result = “Hello World”;
var id = 1;
//DOESN’T WORK
testMock.Setup(r => r.Test(id, filterExpression)).Returns(result);
//WORKS
testMock.Setup(r => r.Test(id, null)).Returns(result);
//Test
[TestMethod]
public void test()
{
var fe = new FilterExpression();
var id = 1;
_testRepository.Test(id, fe);
_testRepository.Test(id, null);
}
Arguments don't match. You use different FilterExpressions. Have you tried to put any FilterExpression?
testMock.Setup(r => r.Test(id, It.IsAny<FilterExpression>())).Returns(result);
Your setup should contain the original object; in your code sample it does not:
testMock.Setup(r => r.Test(id, filterExpression)).Returns(result);
to
testMock.Setup(r => r.Test(id, fe)).Returns(result);
According to your test above. Also, where is your setup of the test objects defined? these should also be defined within the test itself.
If you are trying to unit test Dynamics CRM code, then did you try FakeXrmEasy?
It's an open source project I have been working on since 2014 which automatically mocks IOrganizationService calls for you, including your FilterExpressions, but also any QueryExpression (with joins, filters, nested linked entities, order by), QueryByAttribute, FetchXml, the main basic CRUD and also other messages like Associate, Disassociate, ExecuteMultiple, WhoAmIRequests, and so on and so on...
It's really robust, it has more 800+ unit tests to test the testing framework itself (yeah, how meta is that? ) and the feedback, like this one, is excellent! :)
It definetely helps me on a daily basis and though of open sourcing it to help other CRM developers, and also so that other developers from the community could also contribute with their own improvements and new features (please do so).
It is available as a NuGet package too which makes it really easy to get started with. Please have a look at the documentation page here.
I actually started working on another repository to do the same thing for Web API calls from Javascript.
Stay tunned & happy testing!

How to get tests in unit test project to be run (when the method has parameters)

I have a unit test I want to named parameters in, e.g:
[TestMethod]
public void Register(bool DoSeed = false, AccountViewModelForReg VM = null)
{
AutoMapperConfig.Configure(); //TODO move to global
AccountController C = new AccountController();
VM = new AccountViewModelForReg()
{
Username = "testuser1",
Password = AccountHelper.HashPassword("a"),
Email = "testuser1"+CommonEmailSuffix,
Email2 = "testuser1"+CommonEmailSuffix
};
var Result = C.Register(VM, true) as ViewResult;
Assert.AreEqual("Register", Result.ViewName);
}
This is so from my EF Seeder, I can use my unit tests to seed, by just passing parameters in. But because the method takes parameters, Visual Studio doesn't count it as a test to be run. How can I get around this?
You can extend MSTest to allow this.
http://blogs.msdn.com/b/vstsqualitytools/archive/2009/09/04/extending-the-visual-studio-unit-test-type-part-2.aspx
AFAIK, VS unit test don't support parameterized unit tests.
Your only way is to write another, parameterless overload and call your method from there. BTW: The optional parameters are nothing but syntactical sugar; the method still requires the parameters.
Example:
public void Test_One(bool p1, string p2)
//...
public void Test_One()
{
Test_One(true, "defaultvalue");
}
You should take a look at another framework, e.g. NUnit, which allows you to easily parametrize your tests (even with ranges, automatic combination of parameters etc.): See http://nunit.org/index.php?p=parameterizedTests&r=2.5

TDD - Using properties to auto-generate code

I am practicing TDD using MsTest together with RhinoMocks, and I am trying to be as lazy as humanly possible, i.e. make use of VS2012 auto-generation wherever I can. But it doesn't always feel right to create an entire test method with the Arrange-Act-Assert methodology, just to set up my class and its constructors and properties.
Currently, I find it easiest to create some properties in my test class - even if I don't use them - solely for the purpose of code generation. My question is, is this a bad habit, and is there a better/easier way to do it? Any commentary, good or bad is welcome; Thank you!
[TestClass]
public class MainViewModelTest
{
private MainViewModel MainViewModel
{
get
{
var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
var viewModel = new MainViewModel(facilityDataEntity)
{
FacilityValue = string.Empty,
FacilityLabel = string.Empty
};
return viewModel;
}
}
private MainViewModel MainViewModelWithFacilityAndShopOrderData
{
get
{
var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
var shopOrderDataEntity = MockRepository.GenerateStub<ShopOrderDataEntity>();
var viewModel = new MainViewModel(facilityDataEntity, shopOrderDataEntity)
{
FacilityValue = string.Empty,
FacilityLabel = string.Empty,
ShopOrder = 99999999,
RequiredQuantity = 0M,
ItemCode = string.Empty,
ItemDescription = string.Empty
};
return viewModel;
}
}
[TestMethod]
public void MainViewModel_TranslateDataEntityListMethodReturnsMainViewModelRecords()
{
// Arrange
var facilityDataEntityList = MockRepository.GenerateStub<IEnumerable<FacilityDataEntity>>();
var shopOrderDataEntityList = MockRepository.GenerateStub<IEnumerable<ShopOrderDataEntity>>();
// Act
IEnumerable<MainViewModel> facilityResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList);
IEnumerable<MainViewModel> shopOrderResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList, shopOrderDataEntityList);
// Assert
Assert.IsInstanceOfType(facilityResults, typeof(IEnumerable<MainViewModel>));
Assert.IsInstanceOfType(shopOrderResults, typeof(IEnumerable<MainViewModel>));
}
}
It's not wrong to wrap up common code within your test classes, but I would avoid potentially sharing state between your tests.
There are two approaches you can use here.
Class/Test Initialization
As Peter mentions in his comments, it's easy enough to include initialization methods to do this sort of stuff for you.
//Only runs once per test run
[ClassInitialize]
public void InitClass(){
//Ideally this should be reserved for expensive operations
// or for setting properties that are static throughout
// the lifetime of your test.
}
//Runs for every test
[TestInitialize]
public void TestInit(){
//Here you can setup common stub/mock behavior
// that will be common for every test, but ensure
// it is clean for each test run
}
Setup/Factory Methods
Another option is to create specialized setup or factory methods that can be used to reduce repeated test code and make the intent of your test clearer.
[TestMethod]
public void ShouldFailIfUserNameIsTed(){
var user = SetupUserScenario("Ted");
var result = _myUserService.Validate(user);
Assert.IsFalse(result);
}
private User SetupUserScenario(String username){
var user = new User();
user.Name = username;
//Do a bunch of other necessary setup
return user;
}
Hopefully this all makes sense, but I would also caution you not to go too crazy with this. If you put too much stuff into setup methods, then your tests will be less clear. You should be able to read the test and figure out what is going on without having to inspect a bunch of other places in the code.
That's what the ClassInitialize functionality is for. I would choose expected and recommended means of doing something before anything else. It's more easily recognizable and takes less time to grok the code.

How to find places in code that must be covered with unit tests

I know it's not so good to write tests after you actually wrote code. I'm unit-testing newbie and feel that unit-testing may deliver many good advantages so I obsessed with an idea to cover as much as possible.
For instance, let we have this code:
public class ProjectsPresenter : IProjectsViewObserver
{
private readonly IProjectsView _view;
private readonly IProjectsRepository _repository;
public ProjectsPresenter(IProjectsRepository repository, IProjectsView view)
{
_view = view;
_repository = repository;
Start();
}
public void Start()
{
_view.projects = _repository.FetchAll();
_view.AttachPresenter(this);
}
}
So looking on code above could you answer me what tests typically I should write on that piece of the code above?
I'm rolling on write tests on constructor to make sure that repository's FetchAll was called and on the view site AttachPresenter is called.
POST EDIT
Here is a my view interface:
public interface IProjectsView
{
List<Project> projects { set; }
Project project { set; }
void AttachPresenter(IProjectsViewObserver projectsPresenter);
}
Here is a view:
public partial class ProjectsForm : DockContent, IProjectsView
{
private IProjectsViewObserver _presenter;
public ProjectsForm()
{
InitializeComponent();
}
public Project project
{
set
{
listBoxProjects.SelectedItem = value;
}
}
public List<Project> projects
{
set
{
listBoxProjects.Items.Clear();
if ((value != null) && (value.Count() > 0))
listBoxProjects.Items.AddRange(value.ToArray());
}
}
public void AttachPresenter(IProjectsViewObserver projectsPresenter)
{
if (projectsPresenter == null)
throw new ArgumentNullException("projectsPresenter");
_presenter = projectsPresenter;
}
private void listBoxProjects_SelectedValueChanged(object sender, EventArgs e)
{
if (_presenter != null)
_presenter.SelectedProjectChanged((Project)listBoxProjects.SelectedItem);
}
}
POST EDIT #2
This is how I test interaction with repository. Is everything allright?
[Test]
public void ProjectsPresenter_RegularProjectsProcessing_ViewProjectsAreSetCorrectly()
{
// Arrange
MockRepository mocks = new MockRepository();
var view = mocks.StrictMock<IProjectsView>();
var repository = mocks.StrictMock<IProjectsRepository>();
List<Project> projList = new List<Project> {
new Project { ID = 1, Name = "test1", CreateTimestamp = DateTime.Now },
new Project { ID = 2, Name = "test2", CreateTimestamp = DateTime.Now }
};
Expect.Call(repository.FetchAll()).Return(projList);
Expect.Call(view.projects = projList);
Expect.Call(delegate { view.AttachPresenter(null); }).IgnoreArguments();
mocks.ReplayAll();
// Act
ProjectsPresenter presenter = new ProjectsPresenter(repository, view);
// Assert
mocks.VerifyAll();
}
I know it's not so good to write tests after you actually wrote code
It's better than not writing tests at all.
Your method works with two external components and that interaction should be verified (in addition to mentioned arguments validation). Checking whether FetchAll was called gives you no value (or checking it returns something - this belongs to ProjectsRepository tests itself) - you want to check that view's projects are set (which will indirectly check whether FetchAll was called). Tests you need are:
verify that view projects are set to expected value
verify that presenter is attached
validate input arguments
Edit: example of how you would test first case (projects are set)
// "RegularProcessing" in test name feels a bit forced;
// in such cases, you can simply skip 'conditions' part of test name
public void ProjectsPresenter_SetsViewProjectsCorrectly()
{
var view = MockRepository.GenerateMock<IProjectView>();
var repository = MockRepository.GenerateMock<IProjectsRepository>();
// Don't even need content;
// reference comparison will be enough
List<Project> projects = new List<Project>();
// We use repository in stub mode;
// it will simply provide data and that's all
repository.Stub(r => r.FetchAll()).Return(projects);
view.Expect(v => v.projects = projects);
ProjectsPresenter presenter = new ProjectsPresenter(repository, view);
view.VerifyAllExpecations();
}
In second case, you'll set expectations on view that its AttachPresenter is called with valid object:
public void ProjectsPresenter_AttachesPresenterToView()
{
// Arrange
var view = MockRepository.GenerateMock<IProjectView>();
view.Expect(v => v.AttachPresenter(Arg<IProjectsViewObserver>.Is.Anything));
var repository = MockRepository.GenerateMock<IProjectsRepository>();
// Act
var presenter = new ProjectsPresenter(repository, view);
// Assert
view.VerifyAllExpectations();
}
I would add simple tests at start , like:
null reference checks
FetchAll() returns any value
Do not add a lot of test code at first time, but refine them after as your dev code mutates.
I would add tests for exception e.g. ArgumentException, corner cases and usual ones of FetchAll().
PS. Does start have to be public?
Pex is an interesting tool that's worth checking out. It can generate suites of unit tests with high code coverage: http://research.microsoft.com/en-us/projects/pex/. It doesn't replace your own knowledge of your code - and which test scenarios are more important to you than others - but it's a nice addition to that.
The purpose of writing tests before writing production code is first and foremost to put you (the developer) in the mind-set of "how will i know when my code works?" When your development is focused on what the result of what working code will look like and not the code itself you are focused on the actual business value obtained by your code and not extraneous concerns (millions of man hours have been spent building and maintaining features users never asked for, wanted, or needed). When you do this you are doing "test driven development".
If you are doing pure TDD the answer is 100% code coverage. That is you do not write a single line of production code that is not already covered by a line of unit test code.
In Visual Studio if you go to Test->Analyze Code Coverage it will show you all of the lines of code that you do not have covered.
Practically speaking its not always feasible to enforce 100% code coverage. Also there are some lines of code that are much more important then others. Determining which depends once again on the business value provided by each line and the consequence of that line failing. Some lines (like logging) may have a smaller consequence then others.

Rhino Mocks Restub function

Sometimes I stub dependencies in test class setup and then want to restub some of them in concrete test. But Rhino mocks remembers only the first stub value and it is a bit inconvenient.
someStub.Stub(x => x.SomeMethod(1)).Return(100);
var value1 = someStub.SomeMethod(1);
someStub.Stub(x => x.SomeMethod(1)).Return(200);
var value2 = someStub.SomeMethod(1);
value 2 will be equal to 100.
Is it a designed behaviour? Are there any workarounds?
I ran into a need to do this myself. I worked around it by using the WhenCalled function where you pass in an action to be executed when the function is called. This will give you more flexibility on what you can return at different points.
More info/activity on this stackoverflow thread:
Rhino Mocks: Re-assign a new result for a method on a stub and here:
Changing previously stubbed calls with Rhino Mocks.
I know this is old but hope it helps someone else.
You can work around it with inheritance. If you have a base test class and some test subclasses that run the tests, you can make the return value a protected property of the base test class, and set the value in the subclasses at a point before base. Initialize is called.
So (using MSTEST) you could have:
in your base class:
protected int ReturnVal{get; set;}
public void Init()
{
someStub = MockRepository.GenerateMock<ISomeStub>();
someStub.Stub(x => x.SomeMethod(1)).Return(ReturnVal);
}
in your subclass:
[TestInitialize]
public override Init()
{
ReturnVal = 200;
base.Init();
}
Yes, this is the designed behaviour.
The workaround I use most of the time is to create a helper method that will set up the stub for you, i.e.:
private X MockX()
{
return MockX(100);
}
private X MockX(int returnValue)
{
var x = MockRepository.GenerateStub<X>();
someStub.Stub(x => x.SomeMethod(1)).Return(returnValue);
return x;
}
and then in your test instead of using a mock created in SetUp, you call the appropriate function. The added benefit is that it is clear that your test is using some special values of the return values.
You can use mocks instead of stubs to record a scenario like that:
[Test]
public void Mytest()
{
var mocks = new MockRepository();
var someMock = mocks.DynamicMock<IFoo>();
someMock.SomeMethod(1);
LastCall.Return(100);
someMock.SomeMethod(1);
LastCall.Return(200);
mock.Replay(); // stop recording, go to replay mode
// actual test, normally you would test something which uses the mock here
int firstResult = someMock.SomeMethod(1);
int secondResult = someMock.SomeMethod(2);
// verify the expectations that were set up earlier
// (will fail if SomeMethod is not called as in the recorded scenario)
someMock.VerifyAll();
}
Mocks in Rhino Mocks are more complicated to set up than stubs. They also mix the definition of behavior with the creation of assertions (the record phase does both), and they rely on the ordering of method calls. This makes for brittle tests; stick to stubs unless you really need mocks.

Categories