Rhino Mocks exception "Expected #1, Actual #0" in apparently working code - c#

I have a piece of code from an old book on MVVM which works, but a test using Rhino Mocks fails with this message:
Test method TestProject.UnitTest1.UpdateCustomer_Always_CallsUpdateWithCustomer threw exception:
Rhino.Mocks.Exceptions.ExpectationViolationException: DataProvider.DoSomething(ConsoleApp.Customer); Expected #1, Actual #0
I'm providing an example which I think is equivalent:
namespace ConsoleApp {
class Program { static void Main () { } }
public class Customer { public string ID { get; set; } }
public class DataProvider {
public virtual Customer GetCustomer (string id) => new Customer ();
public virtual void DoSomething (Customer customer) { }
}
public class ViewModel {
DataProvider _dataProvider;
Customer _customer;
public ViewModel (DataProvider dataProvider, string id) {
_dataProvider = dataProvider;
_customer = new Customer { ID = id };
}
public void DoSomething () => _dataProvider.DoSomething (_customer);
}
}
and the test that fails
namespace TestProject {
[TestClass]
public class UnitTest1 {
[TestMethod]
public void UpdateCustomer_Always_CallsUpdateWithCustomer () {
DataProvider dataProviderMock = MockRepository.GenerateMock<DataProvider> ();
Customer expectedCustomer = new Customer ();
dataProviderMock.Stub (u => u.GetCustomer (Arg<string>.Is.Anything)).Return (expectedCustomer);
ViewModel target = new ViewModel (dataProviderMock, string.Empty);
target.DoSomething ();
dataProviderMock.AssertWasCalled (d => d.DoSomething (expectedCustomer));
}
}
}
I read several posts on this result, e.g. 1 and 2, but this doesn't help me. I read this answer which seems interesting:
I usually get this error when a stubbed method is called with an object argument
that I build in the test and in the tested code the object is built before calling that method.
While this could be a reason for the Rhino Mocks to fail, it seems to be a bug.
My question is: Is there something wrong in my test and there is a bug in Rhino Mocks, or is there a problem with my code?

The test stubs DataProvider.GetCustomer to return an expected customer instance to be used in the assertion, but the example view model does not invoke DataProvider.GetCustomer.
It is using the one initialized in the constructor.
//...
public ViewModel (DataProvider dataProvider, string id) {
_dataProvider = dataProvider;
_customer = new Customer { ID = id };
}
//...
Thus the exception thrown by the test is accurate given the shown example.
That is because the actual instance used by the view model will not be the one used in the assertion when the test is exercised.
//...
dataProviderMock.AssertWasCalled (d => d.DoSomething (expectedCustomer));
In order for the test to behave as expected based on its arrangement the view model would actually have be refactored to decouple from initializing the Customer
For example
public class ViewModel {
DataProvider _dataProvider;
string id;
public ViewModel (DataProvider dataProvider, string id) {
_dataProvider = dataProvider;
this.id = id;
}
public void DoSomething () {
Customer customer = _dataProvider.GetCustomer(id);
_dataProvider.DoSomething (_customer);
}
}
The test should also be more explicit about what it is trying to test
[TestClass]
public class UnitTest1 {
[TestMethod]
public void UpdateCustomer_Always_CallsUpdateWithCustomer () {
//Arrange
DataProvider dataProviderMock = MockRepository.GenerateMock<DataProvider> ();
string id = "FakeId";
Customer expectedCustomer = new Customer { ID = id };
dataProviderMock.Stub (u => u.GetCustomer (id))
.Return (expectedCustomer);
ViewModel target = new ViewModel (dataProviderMock, id);
//Act
target.DoSomething ();
//Assert
dataProviderMock.AssertWasCalled (d => d.DoSomething (expectedCustomer));
}
}
Alternatively, if the view model is as intended then the test needs to assert its expectations differently
[TestClass]
public class UnitTest1 {
[TestMethod]
public void UpdateCustomer_Always_CallsUpdateWithCustomer () {
//Arrange
DataProvider dataProviderMock = MockRepository.GenerateMock<DataProvider> ();
string id = "FakeId";
ViewModel target = new ViewModel (dataProviderMock, id);
//Act
target.DoSomething ();
//Assert
dataProviderMock
.AssertWasCalled (d => d.DoSomething (Arg<Customer>.Matches(c => c.ID == id));
}
}
Note the delegate used in the assertion to verify the characteristics of the expected argument instead of the specific instance passed when it was invoked.

Related

Override Autofixture customization setup

I've a class with several services injected in its constructor. I'm using Autofixture with xUnit.net and NSubstitute, and created an attribute to setup the global customization.
public class AutoDbDataAttribute : AutoDataAttribute
{
public AutoDbDataAttribute() : base(() => new Fixture().Customize(new AutoNSubstituteCustomization()))
{
}
public AutoDbDataAttribute(Type customizationType) : base(() =>
{
var customization = Activator.CreateInstance(customizationType) as ICustomization;
var fixture = new Fixture();
fixture.Customize(new AutoNSubstituteCustomization());
fixture.Customize(customization);
return fixture;
})
{
}
}
I also have a custom customization class that setups the common customization for the test methods in the same class.
public class RevenueProviderCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register<IRevenueContextService>(() =>
{
var contextService = Substitute.For<IRevenueContextService>();
contextService.GetContext().Returns(fixture.Create<RevenueContext>());
return contextService;
});
fixture.Register<ICompanyService>(() =>
{
var companyService = Substitute.For<ICompanyService>();
companyService.Get(Arg.Any<Guid>()).Returns(fixture.Create<Company>());
return companyService;
});
}
}
Now, some of my tests depend on modifying specific properties in the objects returned by the services. So in some cases, I want to modify the RevenueContext and in some cases, I want to modify the Company data.
What I did was creating another object inside the test itself and modify the Returns of the service with the new object, like this:
[Theory]
[AutoDbData(typeof(RevenueProviderCustomization))]
public void ShouldReturnCompanyRevenue(RevenueProvider sut, Company company, [Frozen]IRevenueContextService contextService)
{
var fixture = new Fixture();
RevenueContext context = fixture.Build<RevenueContext>().With(c => c.DepartmentId, null).Create();
contextService.GetContext().Returns(context);
sut.GetRevenue().Should().Be(company.Revenue);
}
But this doesn't work. The RevenueContext from the RevenueProviderCustomization is still used.
Does anyone know how I can override the return from the service? I don't want to setup the fixture one by one in my test, so I was hoping to be able to create a 'general setup' and modify as needed according to the test case.
UPDATE 1
Trying the answer from Mark, I changed the test to
[Theory]
[AutoDbData(typeof(RevenueProviderCustomization))]
public void ShouldReturnCompanyRevenue([Frozen]IRevenueContextService contextService, [Frozen]Company company, RevenueProvider sut, RevenueContext context)
{
context.DepartmentId = null;
contextService.GetContext().Returns(context);
sut.GetRevenue().Should().Be(company.Revenue);
}
The problem is because the RevenueContext is called in the RevenueProvider constructor. So my modification to the DepartmentId happens after the call was made.
public RevenueProvider(IRevenueContextService contextService, ICompanyService companyService)
{
_contextService = contextService;
_companyService = companyService;
_company = GetCompany();
}
public double GetRevenue()
{
if (_hasDepartmentContext)
return _company.Departments.Single(d => d.Id == _departmentId).Revenue;
else
return _company.Revenue;
}
private Company GetCompany()
{
RevenueContext context = _contextService.GetContext();
if (context.DepartmentId.HasValue)
{
_hasDepartmentContext = true;
_departmentId = context.DepartmentId.Value;
}
return _companyService.Get(context.CompanyId);
}
Assuming that RevenueProvider essentially looks like this:
public class RevenueProvider
{
private readonly ICompanyService companySvc;
public RevenueProvider(ICompanyService companySvc)
{
this.companySvc = companySvc;
}
public object GetRevenue()
{
var company = this.companySvc.Get(Guid.Empty);
return company.Revenue;
}
}
Then the following test passes:
[Theory]
[AutoDbData(typeof(RevenueProviderCustomization))]
public void ShouldReturnCompanyRevenue(
[Frozen]ICompanyService companySvc,
RevenueProvider sut,
Company company)
{
companySvc.Get(Arg.Any<Guid>()).Returns(company);
var actual = sut.GetRevenue();
Assert.Equal(company.Revenue, actual);
}
This scenario is exactly what the [Frozen] attribute is designed to handle. The various attributes that AutoFixture defines are applied in the order of the arguments. This is by design, because it enables you to pull out a few values from the argument list before you freeze a type.
In the OP, [Frozen] is only applied after sut, which is the reason the configuration of the mock doesn't apply within the SUT.

Verifying a virtual method (MOQ)

So I am new to TDD and here is my problem:
I have a class with several methods. Something like this:
public class CompanyService : ICompanyService
{
public ICompanyRepository companyRepository;
public CompanyService() : this(new CompanyRepository())
{
}
public CompanyService(ICompanyRepository repository)
{
companyRepository = repository;
}
public virtual bool InsertCompany(Company company)
{
return companyRepository.InsertCompany(company);
}
public bool InsertCompany(Company company, int total)
{
if (AddTotals(total))
{
return this.InsertCompany(company);
}
return false;
}
/// <summary>
/// Wrapper for the static method at static service
/// </summary>
/// <param name="total"></param>
/// <returns></returns>
public virtual bool AddTotals(int total)
{
return StaticService.AddTotals(total);
}
}
Most of my tests run fine for this class. So here is my unit test:
[TestMethod]
public void Test_Unit_AddTotals()
{
var service = new CompanyService();
Assert.IsFalse(service.AddTotals(1));
}
[TestMethod]
public void Test_Unit_InsertCompany_IsExecuted()
{
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Object.InsertCompany(company, 1);
mock.Verify(t => t.InsertCompany(It.IsAny<Company>()),Times.Once);
}
[TestMethod]
public void Test_Unit_InsertCompany_IsSuccess()
{
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Setup(t => t.InsertCompany(It.IsAny<Company>(), It.IsAny<int>())).Returns(true);
Assert.IsTrue(mock.Object.InsertCompany(company, 1));
}
[TestMethod]
public void Test_Unit_StaticService()
{
var rep = new Mock<ICompanyRepository>();
rep.Setup(t => t.InsertCompany(It.IsAny<Company>())).Returns(true);
var serviceMock = new Mock<ICompanyService>();
serviceMock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
Assert.IsTrue(serviceMock.Object.AddTotals(0));
}
private Guid GenerateCustomerID()
{
return Guid.NewGuid();
}
So when I make my 2 parameter InsertCompany method virtual my IsExecuted method fails at Verify, if I make it non-virtual, then I can't mock it for IsSuccess method and it fails..
Could you please tell me what I am missing with your TDD expertise?
As has been suggested in the comments, you're almost certainly not testing the right thing. Look at this test:
[TestMethod]
public void Test_Unit_InsertCompany_IsSuccess()
{
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Setup(t => t.InsertCompany(It.IsAny<Company>(), It.IsAny<int>())).Returns(true);
Assert.IsTrue(mock.Object.InsertCompany(company, 1));
}
If your class is marked with the right virtual state for the Setup to execute, then you're not actually testing any of your class at all. You're setting up the Mock to return true when a method is called, then asserting that when you call the method the mock returns true... You're just testing that you've set your Mocks up correctly.
When you mark the method as virtual, your mocking used in the IsExecuted method is failing, because you're calling virtual methods from within the class under test. If you don't tell it to, Moq will assume that if you're doing a partial mock, you only want your mocked virtuals to be called, not the existing implementation. You can override this by telling Moq to call your existing implementation by setting the CallBase flag.
Your test would then become this:
[Test]
public void Test_Unit_InsertCompany_IsExecuted() {
Guid id = GenerateCustomerID();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>();
mock.CallBase = true;
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Setup(t => t.InsertCompany(It.IsAny<Company>()));
mock.Object.InsertCompany(company, 1);
mock.Verify(t => t.InsertCompany(It.IsAny<Company>()), Times.Once);
}
Two things to note are
In the above test, CallBase=true is used to execute existing code.
As a result of 1, it's necessary to perform a Setup for the call you want to verify, otherwise the call will actually execute the underlying code and call out to the repository.
Testing that one method calls another method in the same class isn't really a great idea. It can get very messy and makes it difficult to know that what you're expecting to happen is actually what's happening as well as tightly coupling your implementation to your test code.
You've already setup your Company class to allow the injection of a repository. Testing that the appropriate repository interactions take place would result in less coupling to the implementation of your Company class and would probably result in more straightforward mocking.
Using that approach, your IsExecuted test might become:
[Test]
public void Test_Unit_InsertCompany_SavesToRepository() {
Guid id = GenerateCustomerID();
var repoMock = new Mock<ICompanyRepository>();
var company = new Company { CustomerID = id, CompanyName = "CFN-" + id };
var mock = new Mock<CompanyService>(repoMock.Object);
mock.CallBase = true;
mock.Setup(t => t.AddTotals(It.IsAny<int>())).Returns(true);
mock.Object.InsertCompany(company, 1);
repoMock.Verify(t => t.InsertCompany(It.IsAny<Company>()), Times.Once);
}
Ideally, you'd be able to Mock the interaction with StaticService.AddTotals, that way you would be able to instantiate an actual CompanyService, rather than a mock object in your tests, however that seems out of scope for your current problem...

Issue with Unit Testing Model View Presenter

I am creating an application in ASP.NET web form with MVP pattern. I am getting some issues working with TDD. I have created two test, one is working fine but when a second test is executed it throws an error.
Below is my declared View
public interface IAddUpdateView : IView
{
string Type { get; set; }
string PageTitle { set; }
string Details { get; set; }
bool Active { get; set; }
}
Presenter
// BasePresenter is an abstract class contains abstract method with name Initialize()
public class MyPresenter: BasePresenter<IAddUpdateView >
{
private readonly IDatabaseLayer _databaselayer;
public MyPresenter(IAddUpdateView view, IDatabaseLayer databaseLayer) : base(view)
{
_databaselayer = databaseLayer;
}
public override void Initialize()
{ }
public void Initialize(string str)
{
string[] str1=Misc.DecryptURL(str);
View.Type = str1[0].ToString(); // ERROR LINE
if (View.Type.ToLower().Trim() == "add")
{
View.PageTitle = "Add New Task";
}
else if (View.Type.ToLower().Trim() == "edit")
{
}
}
}
Now I am working on creating unit test mocking the Presenter class to test the dependencies using Rhino mocks.
That's my test class with just two test methods. These test methods test when loading a View it calls appropriate Page Type.
When ADD type is called, it get the View.Type as "add" and when Edit type is called, it verifies for the specific object that is loaded.
[TestFixture]
public class MyPresenterTest
{
private IAddUpdateView _view;
private MyPresernter _controller;
[SetUp]
public void SetUp()
{
_view = MockRepository.GenerateMock<IAddUpdateView >();
_controller = new MyPresernter (_view, MockDataLayer());
}
[TearDown]
public void TearDown() { _controller = null; _view = null; }
// TEST 1
[Test]
public void When_Loading_for_Add_View_Panel_Return_Type_Add()
{
// Arrange
_view.Stub(x => x.Type).PropertyBehavior();
//Act
_controller.Initialize(GetURLWithAddValue());
// GetURLWithAddValue: This method get the URL with querystring contains value as "add"
//Assert
Assert.AreEqual("add",_view.Type);
}
TEST 2
// When this test method is run, It has the Type="edit", but in my
presenter View.Type (see LINE ERROR), my Type is null even I
assigned the values.
[Test]
public void When_Loading_for_Edit_View_Panel_Load_Correct_Object()
{
// Arrange
_view.Stub(x =>x.TaskDetails).PropertyBehavior();
//Act
Task o=new Task(){ TaskId=6, TASK_NAME="Task 6"};
_controller.Initialize(GetURLWithEditValue(o));
//Assert
Assert.AreEqual(o.TASK_NAME, _view.TaskDetails);
}
private static IDatabaseLayer MockDataLayer()
{
IDatabaseLayer obj = MockRepository.GenerateMock<IDatabaseLayer>();
MockTaskDataLayer a = new MockTaskDataLayer();
obj.Stub(x => x.GetList());
return obj;
}
}
Can someone guide me why Test 1 get passed and when Test 2 is executed, after assigning a value in View.Type (see LINE ERROR in MyPresenter class) it's still null??
Thanks,

Moq Verify with anonymous type parameter

I have the following test, with supporting classes, but I can't figure out how to verify the call on the dependency.
[TestFixture]
public class AnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var towns = new List<Town>
{
new Town { Name = "Lifford", County = "Donegal", Country="Ireland", Population = 1658 },
new Town { Name = "Ballyshannon", County = "Donegal", Country="Ireland", Population = 2504 },
new Town { Name = "Buxton", County = "Derbyshire", Country="United Kingdom", Population = 13599 },
};
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething(towns);
// Assert
// The following line needs to be fixed.
dependency.Verify(d => d.Execute(It.IsAny<IEnumerable<object>>(), It.IsAny<Func<object, decimal?>>()));
}
}
public interface IDependency
{
void Execute<T>(IEnumerable<T> collection, Func<T, decimal?> rateSelector);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(IEnumerable<Town> towns)
{
var counties = towns.GroupBy(t => new {t.Country,t.County});
foreach (var county in counties)
{
dependency.Execute(county, c => c.Population);
}
}
}
public class Town
{
public string Name { get; set; }
public string County { get; set; }
public int Population { get; set; }
public string Country { get; set; }
}
According to Moq's test output, the performed invocations are:
Dependency.Execute(System.Linq.Lookup`2+Grouping[<>f__AnonymousType0`2[System.String,System.String],UniFocus.Staffscope4.Tests.Town], System.Func`2[UniFocus.Staffscope4.Tests.Town,System.Nullable`1[System.Decimal]])
I see plenty of questions regarding anonymous parameters in Moq (such as this and this and this), but can't find anything relating to using an anonymous type as the actual type parameter.
What can be put in the Verify line so that it actually verifies the call inside?
Note: My example IDependency doesn't return a value (it's already complex enough, I think), but there will be bonus kudos for answers that implictly or explicitly address Setup() as well as Verify().
Update
Jesse's solution only passes the test because I made a bad choice when crafting my example. I should have realised that any IGrouping<out TKey, out TElement> is also an IEnumerable<TElement>. Is there a more universal solution?
Update 2
I feel like my original example was possibly too elaborate and didn't represent well the actual title of my question. Is there any solution that works for this more straightforward and to-the-point example?
using Moq;
using NUnit.Framework;
namespace Tests
{
[TestFixture]
public class SimpleAnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething("Donegal", "Lifford");
// Assert
// This verify works for both calls to Execute()
dependency.Verify(d => d.Execute(It.IsAny<object>()), Times.Exactly(2));
// This verify should specifically refer to only the first call to Execute()
dependency.Verify(d => d.Execute(It.IsAny</*HowToRepresentAnonymousTypeHere*/object>()), Times.Once);
}
public interface IDependency
{
void Execute<T>(T thing);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(string county, string town)
{
dependency.Execute(new { county, town });
object someUnknownObject = "";
dependency.Execute(someUnknownObject);
}
}
}
}
The accepted answer doesn't work for me, I believe it's because the tests and the object in question are in a different assembly so Moq doesn't know how to reconcile the types and does not match them.
Instead, I created the following helper methods that can verify that the anonymous type provided has the correct fields and values:
public static class AnonHelpers
{
public static object MatchAnonymousType(object expected)
{
return Match.Create(Matcher(expected));
}
private static Predicate<object> Matcher(object expected)
{
return actual =>
{
var expectedProp = expected.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(expected));
var actualProp = actual.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(actual));
foreach (var prop in expectedProp)
{
if (!actualProp.ContainsKey(prop.Key))
return false;
if (!prop.Value.Equals(actualProp[prop.Key]))
return false;
}
return true;
};
}
}
They can be used like so:
var anon = new { SomeKey = "some value", SomeOtherKey = 123 };
myMock.Setup(x => x.MyMethod(personIDs, AnonHelpers.MatchAnonymousType(anon))).Verifiable();
This will create a matcher that will use reflection to match the anonymous type based on it's keys and values and then you can use normal verification to see when it's been called.
Since the types are known in the context of the test, you could provide the specific type arguments to the Verify call. The following change got the test to pass:
dependency.Verify(d =>
d.Execute(It.IsAny<IEnumerable<Town>>(), It.IsAny<Func<Town, decimal?>>()));
The same should also work for setups.
With regards to the example in Update 2, the following passes, but it requires knowledge of the inner workings of the DoSomething() method and as far as I know it's the only way to make it work:
var anonymousType = new {county = "Donegal", town = "Lifford"};
dependency.Verify(d => d.Execute(anonymousType), Times.Once);

Unit testing FluentValidation rules for classes with sub/child classes

Is it possible to write unit tests for fluentvalidation classes when the object we are validating has child classes that are also being validated.
As an example:
My class looks like this
public class TestModel
{
public class SubData
{
public int SubDataVal { get; set; }
}
public int ParentVal { get; set; }
public SubData Sub { get; set; }
}
My validation logic looks like this:
public class TestModelValidator : AbstractValidator<TestModel>
{
public TestModelValidator()
{
RuleFor(o => o.ParentVal).GreaterThan(0);
RuleFor(o => o.Sub.SubDataVal).GreaterThan(0);
}
}
And when I write the following unit test
[Test]
public void Should_have_error_when_val_is_zero()
{
validator = new TestModelValidator();
validator.ShouldHaveValidationErrorFor(model => model.ParentVal, 0);
}
I get a "System.NullReferenceException : Object reference not set to an instance of an object." exception from
FluentValidation.TestHelper.ValidatorTester`2.ValidateError(T instanceToValidate)
(if I remove the RuleFor(o => o.Sub.SubDataVal).GreaterThan(0); line, then it works!)
Similarly if I try and unit test the actual child class with:
[Test]
public void Should_have_error_when_sub_dataVal_is_zero()
{
validator = new TestModelValidator();
validator.ShouldHaveValidationErrorFor(model => model.Sub.SubDataVal, 0);
}
I get a "System.Reflection.TargetException : Object does not match target type." from FluentValidation.TestHelper.ValidatorTester`2.ValidateError(T instanceToValidate)
You can unit test models and child models but you will need to change your validation class to use a separate validator class which just validates the child model:
public class TestModelValidator : AbstractValidator<TestModel>
{
public TestModelValidator()
{
RuleFor(o => o.ParentVal).GreaterThan(0);
RuleFor(o => o.Sub).SetValidator(new SubDataValidator());
}
}
public class SubDataValidator : AbstractValidator<SubData>
{
public SubDataValidator()
{
RuleFor(o => o.SubDataVal).GreaterThan(0);
}
}
You can then write your unit tests to test each validator or both together.
I have come to the conclusion that for this ShouldHaveValidationErrorFor is just not capabable of dealing with subclasses, so have resorted to doing it manually. i.e.
[Test]
public void Should_have_error_when_val_is_zero()
{
validator = new TestModelValidator();
TestModel testRequest = new TestModel();
//populate with dummy data
var result = validator.Validate(testRequest);
Assert.That(result.Errors.Any(o => o.PropertyName== "ParentVal"));
}
With MSTest and FluentAssertions you can write
[TestMethod]
public void Should_have_error_when_val_is_zero()
{
// Given
var validator = new TestModelValidator();
var testModel = TestModel
{
ParentVal = 0
}; // You should create a invalid TestModel object here
// When
validator.Validate(testModel).IsValid.Should().BeFalse();
}
For anyone getting here as I did.
As all rules are executed during the Validation you need to set the whole model to reasonable values.
With current version you can do following:
//using FluentValidation;
//using FluentValidation.TestHelper;
[Fact]
public void Should_have_error_when_val_is_zero()
{
var validator = new TestModelValidator();
var model = new TestModel()
{
ParentVal = 0,
Sub = new TestModel.SubData()
};
var result = validator.TestValidate(model);
result.ShouldHaveValidationErrorFor(model => model.ParentVal);
//result.ShouldHaveValidationErrorFor(nameof(TestModel.ParentVal));
}

Categories