I have this code:
Class VM
{
var MyVm;
public VM(ExternalEntities externalEntities){
MyVm = externalEntities.Reflcation.VM;
}
public bool IsVmPowerOn(){
//Do something
}
}
[TestMethod]
public void TestVM()
{
private Mock<IExternalEntities> m_externalEntities = new Mock<IExternalEntities>();
private Mock<IReflection> m_reflection = new Mock<IReflection>();
private Mock<IVm> m_vm= new Mock<IVm>();
m_externalEntities.Setup(x => x.Reflaction).Return(m_reflection.object);
m_reflection.Setup(x => x.VM).Return(m_vm.Object);
var testee = new VM(externalEntity.Object)
var ans = testee.IsVmPowerOn();
Assert.IsTrue(ans);
}
The problem is that externalEntities.Reflcation is null and the test throws a NullReferenceException so it can't activate the Vm property.
The test can't pass constructor.
The following code also throws a NullReferenceException:
m_externalEntities.Setup(x => x.Reflaction.VM).Return(m_vm.object);
How do you test this kind of code?
Why do I receive null after the setup and not the mock object?
You had a lot of compilation errors and missing pieces in your code. It was not compiling as-is. That being said, I fixed it up for you. Not sure what your trying to accomplish but this works.
public interface IVm
{
IVm MyVm { get; set; }
}
public class VM : IVm
{
public IVm MyVm { get; set; }
public VM(IExternalEntities externalEntities)
{
MyVm = externalEntities.Reflaction.VM;
}
public bool IsVmPowerOn()
{
//Do something
return true;
}
}
public interface IExternalEntities
{
IReflection Reflaction { get; set; }
}
public class ExternalEntities : IExternalEntities
{
public IReflection Reflaction { get; set; }
public ExternalEntities()
{
Reflaction = new Reflection();
}
}
public interface IReflection
{
IVm VM { get; set; }
}
public class Reflection : IReflection
{
public IVm VM { get; set; }
public Reflection()
{
VM = new VM(null);
}
}
Then using that, your test would look like this.
[TestMethod]
public void TestVM()
{
Mock<IExternalEntities> m_externalEntities = new Mock<IExternalEntities>();
Mock<IReflection> m_reflection = new Mock<IReflection>();
Mock<IVm> m_vm = new Mock<IVm>();
m_externalEntities.Setup(x => x.Reflaction).Returns(m_reflection.Object);
m_reflection.Setup(x => x.VM).Returns(m_vm.Object);
var testee = new VM(m_externalEntities.Object);
var ans = testee.IsVmPowerOn();
Assert.IsTrue(ans);
}
Related
I'm working on Unit test. I create TestBuilder class, where I create method SetupTown method.
When I tried call this method in my main test class - i have error( Error CS0118'TestBuilder' is a namespace but is used like a type). I read about it and recommend to call a class with method. I tried do it, but It doesn't help.
public partial class TownServiceTests
public partial class TownServiceTests
{
private class TestBuilder
{
public Mock<ITownRepository> MockTownRepository { get; set; }
//public Mock<IClientViewModelBuilder> MockClientPropertyModelBuilder { get; set; }
public Mock<IMapper> MockMapper { get; set; }
public TestDataGenerator TestDataGenerator;
private readonly string _jsonDataPath = #"../../../TestData/Town/TownTestData.json";
private string _jsonDataKey;
private TownViewModel Towns { get; set; }
public TestBuilder(string jsonDataKey)
{
MockTownRepository = new Mock<ITownRepository>();
//MockClientPropertyModelBuilder = new Mock<IClientViewModelBuilder>();
MockMapper = new Mock<IMapper>();
TestDataGenerator = new TestDataGenerator(_jsonDataPath);
_jsonDataKey = jsonDataKey;
TestDataGenerator.LoadData(_jsonDataKey);
}
public ITownService Build()
{
return new TownService(MockTownRepository.Object,
MockMapper.Object);
}
public TestBuilder SetupTowns()
{
var towns = TestDataGenerator.GetTestData<Town>(_jsonDataKey, "Towns");
MockTownRepository.Setup(r => r.InsertTown(It.IsAny<string>()))
.ReturnsAsync(towns.FirstOrDefault().Id);
return this;
}
}
}
}
Please check method public TestBuilder SetupTowns
Here my TestClass
[TestClass]
public partial class TownServiceTests
{
[TestMethod]
public async Task ValidInsertTown()
{
var builder = new TestBuilder("Data").SetupTowns; //Problem
var service = builder.Build();
var expectedTowns = builder.TestDataGenerator.GetTestData<Town>("Data", "Towns");
var result = await service.InsertTown(expectedTowns);
Assert.IsNotNull(result);
Assert.IsNull(result);
}
}
Could toy tell me what I do wrong?
Example
public partial class ClientServiceTests
{
private class TestBuilder
{
public Mock<IClientRepository> MockClientRepository { get; set; }
public Mock<IClientViewModelBuilder> MockClientPropertyModelBuilder { get; set; }
public Mock<IMapper> MockMapper { get; set; }
public TestDataGenerator TestDataGenerator;
private readonly string _jsonDataPath = #"../../../TestData/Client/ClientTestData.json";
private string _jsonDataKey;
public TestBuilder(string jsonDataKey)
{
MockClientRepository = new Mock<IClientRepository>();
MockClientPropertyModelBuilder = new Mock<IClientViewModelBuilder>();
MockMapper = new Mock<IMapper>();
TestDataGenerator = new TestDataGenerator(_jsonDataPath);
_jsonDataKey = jsonDataKey;
TestDataGenerator.LoadData(_jsonDataKey);
}
public IClientService Build()
{
return new ClientService(MockClientRepository.Object
, MockClientPropertyModelBuilder.Object
, MockMapper.Object);
}
public TestBuilder SetupClients()
{
var clients = TestDataGenerator.GetTestData<ClientSummary>(_jsonDataKey, "Clients");
MockClientRepository.Setup(r => r.GetClientBySearchCriteria(It.IsAny<string>()))
.ReturnsAsync(clients);
var clientViewModels = TestDataGenerator.GetTestData<ClientViewModel>(_jsonDataKey, "ClientViewModel");
MockClientPropertyModelBuilder.Setup(r => r.GetClientViewModel(clients))
.Returns(clientViewModels);
return this;
}
public TestBuilder SetupInvalidInputClients()
{
MockClientRepository.Setup(r => r.GetClientBySearchCriteria(It.IsAny<string>()))
.ReturnsAsync(new List<ClientSummary>());
MockClientPropertyModelBuilder.Setup(r => r.GetClientViewModel(new List<ClientSummary>()))
.Returns(new List<ClientViewModel>());
return this;
}
}
}
TestClass (here works good)
[TestMethod]
public async Task GetClientBySearchCriteria_ValidInput_ReturnClients()
{
var searchParameter = "1";
var builder = new TestBuilder("Data").SetupClients();
var service = builder.Build();
var expectedClients = builder.TestDataGenerator.GetTestData<ClientSummary>("Data", "Clients");
var result = await service.GetClientBySearchCriteria(searchParameter);
Assert.IsNotNull(result);
Assert.AreEqual(2, result.Count);
Assert.AreEqual(expectedClients.FirstOrDefault().Name, result.FirstOrDefault().Name);
}
namespace of the file
I think, the issue is happened because you have Something.TestBuilder.Something namespace and compiler is trying to use it instead of class.
You have the TestBuilder folder and a few classes inside it. It may be that classes inside TestBuilder folder contains TestBuilder in their namespaces and compiler trying to access this namespace instead of class.
I have this class POCO
public class BankTransaction
{
public int Id { get; set; }
public decimal TransactionAmount { get; set; }
public TransactionTypeEnum TransactionType { get; set; }
public int BankAccountId { get; set; }
public BankTransaction(decimal TransactionAmount)
{
this.TransactionAmount = TransactionAmount;
}
}
public enum TransactionTypeEnum
{
Deposit, Withdraw, ThirdPartyTransfer
}
and this repository class insert the transaction
public class BankTransactionRepository : IBankTransactionRepository
{
// Mock DB
public List<BankTransaction> bankTransactions { get; private set; }
public BankTransactionRepository()
{
bankTransactions = new List<BankTransaction>();
}
public void InsertTransaction(BankTransaction bankTransaction)
{
bankTransactions.Add(bankTransaction);
}
}
and here is my xUnit unit test for InsertTransaction method which works except for expected.Should().Contain(trans); which support to check if trans object exists in expected list.
public class BankTransactionsTest
{
private BankTransactionRepository _bankTransaction;
public BankTransactionsTest()
{
_bankTransaction = new BankTransactionRepository();
}
// Arrange
[Theory, MemberData(nameof(InsertTransaction_InsertShouldPass_Data))]
public void InsertTransaction_InsertShouldPass(BankTransaction trans, List<BankTransaction> expected)
{
// Act
_bankTransaction.InsertTransaction(trans);
// Assert
Assert.Equal(expected.Count, _bankTransaction.bankTransactions.Count);
// Fluent Assertions to check if trans is in 'expected' list.
expected.Should().Contain(trans);
}
public static TheoryData<BankTransaction, List<BankTransaction>> InsertTransaction_InsertShouldPass_Data()
{
return new TheoryData<BankTransaction, List<BankTransaction>>
{
{
new BankTransaction(200.00M),
new List<BankTransaction>(){new BankTransaction(200.00M)}
},
{
new BankTransaction(50.50M),
new List<BankTransaction>(){new BankTransaction(50.50M)}
},
};
}
}
Change the approach to be more explicit about asserting the expected behavior:
That the object inserted when InsertTransaction is invoked, is actually contained in the subject under test.
public class BankTransactionsTest
{
private BankTransactionRepository _bankTransaction;
public BankTransactionsTest()
{
_bankTransaction = new BankTransactionRepository();
}
// Arrange
[Theory, MemberData(nameof(InsertTransaction_InsertShouldPass_Data))]
public void InsertTransaction_InsertShouldPass(BankTransaction transaction)
{
// Act
_bankTransaction.InsertTransaction(transaction);
// Assert
_bankTransaction.bankTransactions.Should().ContainEquivalentOf(transaction);
}
public static TheoryData<BankTransaction> InsertTransaction_InsertShouldPass_Data()
{
return new TheoryData<BankTransaction>
{
new BankTransaction(200.00M),
new BankTransaction(50.50M)
};
}
}
The problem is that we have more than thousend database tables with properties that have a dynamic postfix (e.g. properties like: Name_A1234, Name_B4567, Name_H123). Now we want to use AutoMapper to map this properties to DataModels with properties without this postfixes. The solution with the ForMember function is to time expansive and also produces too much code.
I've tried the following to solve this issue:
public class A
{
public string Name_XY1234 { get; set; }
}
public class B
{
public string Name_AB1234 { get; set; }
}
public class C
{
public string Name { get; set; }
}
public class MyNamingConvention : INamingConvention
{
private readonly Regex _splittingExpression = new Regex(#"\A[a-zA-Z0-9]+(?=_?.*)");
public string SeparatorCharacter
{
get { return string.Empty; }
}
public System.Text.RegularExpressions.Regex SplittingExpression
{
get { return _splittingExpression; }
}
}
public class Test
{
public Test()
{
try
{
Mapper.Initialize(cfg =>
{
cfg.SourceMemberNamingConvention = new MyNamingConvention();
cfg.DestinationMemberNamingConvention = new MyNamingConvention();
});
AutoMapper.Mapper.CreateMap<A, C>();
var a = new A();
a.Name_XY1234 = "Test";
var c = AutoMapper.Mapper.Map<C>(a);
// should be Test...
System.Diagnostics.Debug.WriteLine(c.Name);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
}
Unfortunately this doesn't work.
How can I solve this issue?
Thank you.
I have a test method...
[TestMethod]
public void MainViewModel_PropertiesReflectDataEntityProperties()
{
// Arrange
var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
var shopOrderDataEntity = MockRepository.GenerateStub<ShopOrderDataEntity>();
// Act
MainViewModel mainViewModel = new MainViewModel(facilityDataEntity, shopOrderDataEntity);
// Assert
Assert.AreSame(facilityDataEntity.Value, mainViewModel.FacilityValue);
}
... and the test passes. However, I have not implemented the mapping of the DataEntity's properties to the MainViewModel's properties yet! How can this be? I thought AreSame checks whether two references point to the same instance.
public class MainViewModel
{
private readonly FacilityDataEntity facilityDataEntity;
private readonly ShopOrderDataEntity shopOrderDataEntity;
public MainViewModel(FacilityDataEntity facilityDataEntity)
{
this.facilityDataEntity = facilityDataEntity;
}
public MainViewModel(FacilityDataEntity facilityDataEntity, ShopOrderDataEntity shopOrderDataEntity)
{
this.facilityDataEntity = facilityDataEntity;
this.shopOrderDataEntity = shopOrderDataEntity;
}
public ShopOrderDataEntity ShopOrderDataEntity
{
get { return shopOrderDataEntity; }
}
public FacilityDataEntity FacilityDataEntity
{
get { return facilityDataEntity; }
}
public int ShopOrder { get; set; }
public decimal RequiredQuantity { get; set; }
public string ItemCode { get; set; }
public string ItemDescription { get; set; }
public string FacilityValue { get; set; }
public string FacilityLabel { get; set; }
public static IEnumerable<MainViewModel> TranslateDataEntityList(IEnumerable<FacilityDataEntity> facilityDataEntityList)
{
foreach (FacilityDataEntity facilityDataEntity in facilityDataEntityList)
{
yield return new MainViewModel(facilityDataEntity);
}
}
public static IEnumerable<MainViewModel> TranslateDataEntityList(FacilityDataEntity facilityDataEntity, IEnumerable<ShopOrderDataEntity> shopOrderDataEntityList)
{
foreach (ShopOrderDataEntity shopOrderDataEntity in shopOrderDataEntityList)
{
yield return new MainViewModel(facilityDataEntity, shopOrderDataEntity);
}
}
}
Underneath it all, these tests are just using Object.ReferenceEquals:
true if objA is the same instance as objB or if both are null; otherwise, false.
I guess this is happening because they are both null.
in this case, I'd say its comparing null with null, which are the same.
I want to use AbstractValidator<T> inside base entity class.
[Serializable]
public abstract class Entity<T> where T : Entity<T>
{
public virtual Boolean Validate(AbstractValidator<T> validator)
{
return validator.Validate(this as ValidationContext<T>).IsValid;
}
// other stuff..
}
But one of my tests fails saying that Validate() method couldn't accept null as a paramter.
[Test]
public void CategoryDescriptionIsEmpty()
{
var category = new Category
{
Title = "some title",
Description = String.Empty
};
Assert.False(category.Validate(this.validator) == true);
}
[SetUp]
public void Setup()
{
this.validator = new CategoryValidator();
}
I'm using Visual Web Developer and at the moment can't install C# Developer Express to create console application to debug the error. Since that I don't know how do I debug inside the unit test. Alternatively it would be great if some explanation could be given!
Thanks!
This topic is old, but I found useful and made a little diferent:
public abstract class WithValidation<V> where V : IValidator
{
private IValidator v = Activator.CreateInstance<V>();
public bool IsValid => !(Errors.Count() > 0);
public IEnumerable<string> Errors
{
get
{
var results = v.Validate(this);
List<string> err = new List<string>();
if (!results.IsValid)
foreach (var item in results.Errors)
err.Add(item.ErrorMessage);
return err;
}
}
}
public class Client : WithValidation<ClientValidator>
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
public class ClientValidator : AbstractValidator<Client>
{
public ClientValidator()
{
RuleFor(c => c.Name).NotNull();
RuleFor(c => c.Age).GreaterThan(10);
}
}
So you can use easier now like:
Client c = new Client();
var isvalid = c.IsValid;
IList<string> errors = c.Errors;
Ok!
So solution to my problem is next (at least this works as expected):
public abstract class Entity<T> where T : Entity<T>
{
public Boolean IsValid(IValidator<T> validator)
{
// var context = new ValidationContext(this);
// var instance = context.InstanceToValidate as T;
// return validator.Validate(instance).IsValid;
return validator.Validate(this as T).IsValid;
}
}
public class Rambo : Entity<Rambo>
{
public Int32 MadnessRatio { get; set; }
public Boolean CanHarmEverything { get; set; }
}
public class RamboValidator : AbstractValidator<Rambo>
{
public RamboValidator()
{
RuleFor(r => r.MadnessRatio).GreaterThan(100);
}
}
class Program
{
public static void Main(String[] args)
{
var ramboInstance = new Rambo {
MadnessRatio = 90
};
Console.WriteLine("Is Rembo still mad?");
Console.WriteLine(ramboInstance.IsValid(new RamboValidator()));
Console.ReadKey();
}
}