I am receiving an exception: "object reference not set to an instance of an object".
I am trying to evaluate if Location and Manufacturing classes method ResetAllProperties() are executed.
What em I doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
namespace Test
{
public class Engine
{
public Engine() { }
public EngineStatus Status { get; internal set; }
public virtual EngineLocation Location { get; set; }
public virtual EngineManufacturing Manufacturing { get; set; }
}
public abstract class EngineStatus
{
protected readonly Engine engine = null;
public EngineStatus(Engine engine)
{
this.engine = engine;
}
public abstract void ResetAllProperties();
}
public class FirstEngineStatus : EngineStatus
{
public FirstEngineStatus(Engine engine) : base(engine) { }
public override void ResetAllProperties()
{
this.engine.Location.ResetAllProperties();
this.engine.Manufacturing.ResetAllProperties();
}
}
public class EngineLocation
{
public string CustomerName { get; set; }
public virtual EngineManufacturing Manufacturing { get; set; }
public virtual Engine Engine { get; set; }
public void ResetAllProperties()
{
this.CustomerName = null;
}
}
public class EngineManufacturing
{
public Nullable<DateTime> EntryDate { get; set; }
public virtual EngineLocation Location { get; set; }
public virtual Engine Engine { get; set; }
public void ResetAllProperties()
{
this.EntryDate = null;
}
}
[TestClass]
public class Test
{
[TestMethod]
public void ResetAllProperties_AssertWasCalled()
{
// Arrange
var engine = MockRepository.GenerateMock<Engine>();
var status = MockRepository.GeneratePartialMock<FirstEngineStatus>(engine);
engine.Stub(action => action.Location.ResetAllProperties());
engine.Stub(action => action.Manufacturing.ResetAllProperties());
// Act
status.ResetAllProperties();
// Assert
engine.AssertWasCalled(action => action.Location.ResetAllProperties());
engine.AssertWasCalled(action => action.Manufacturing.ResetAllProperties());
}
}
}
You are asserting the behaviour of Location and Manufacturing, so these are the objects which should be mocked. Also, when checking that something happens use Expects not Stub. Everything else should be concrete. If you make ResetAllProperties methods virtual then the following works:
[TestMethod]
public void ResetAllProperties_AssertWasCalled()
{
var location = MockRepository.GeneratePartialMock<EngineLocation>();
var manufacturing = MockRepository.GeneratePartialMock<EngineManufacturing>();
// Arrange
var engine = new Engine
{
Location = location,
Manufacturing = manufacturing
};
var status = new FirstEngineStatus(engine);
location.Expect(action => action.ResetAllProperties());
manufacturing.Expect(action => action.ResetAllProperties());
// Act
status.ResetAllProperties();
// Assert
location.VerifyAllExpectations();
manufacturing.VerifyAllExpectations();
}
However, this seems like you are testing the implementation rather than the functionality. What do you actually want to test? It looks to me like you want to test that CustomerName and EntryDate are set to null. You can test this without using any mocking at all as follows:
[TestMethod]
public void ResetAllProperties_AssertWasCalled()
{
// Arrange
var engine = new Engine
{
Location = new EngineLocation { CustomerName = "Dzenan" },
Manufacturing = new EngineManufacturing { EntryDate = DateTime.Today }
};
var status = new FirstEngineStatus(engine);
// Act
status.ResetAllProperties();
// Assert
Assert.IsNull(engine.Location.CustomerName);
Assert.IsNull(engine.Manufacturing.EntryDate);
}
Related
I'm in search of a simple way to test that a collection contains logically equivalent object (ignoring instance) in c#.
public class BarObject
{
public string name { get; set; }
public string info { get; set; }
}
public class Foo
{
public Foo() { }
public IEnumerable<BarObject> Bars { get; set; } =
new List<BarObject>()
{
new BarObject() { name = "johndoe", info = "wierdo" }
};
}
[TestClass]
public class FooTests
{
[TestMethod]
public void TestDefaultInList()
{
Foo foo = new Foo();
//Using NUnit
CollectionAssert.Contains(foo.Bars.ToList(),
new BarObject() { name = "johndoe", info = "wierdo" }
);
}
}
The issue that I believe that I am having is that it is checking the instance of the object instead of the values within. How do I test that there is an object with specific values in an array simply without writing my own comparers?
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)
};
}
}
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);
}
I'm having a hard trying to find to correct approach to this :
My data structures :
public abstract class Flow
{
public virtual double Value { get; set; }
public virtual DateTime Time { get; set; }
}
public class InboundFlow : Flow
{
}
public class OutboundFlow : Flow
{
}
My business objects containing collections of these data structures
public abstract class Fluent
{
public virtual IList<Flow> FlowCollection { get; set; }
public virtual double InitialBaseflow { get; set; }
}
public class Affluent : Fluent
{
public new virtual IList<InboundFlow> FlowCollection { get; set; }
}
public class Effluent : Fluent
{
public new virtual IList<OutboundFlow> FlowCollection { get; set; }
}
The generic method I'm trying to use :
private static void FindInitialBaseflow<T>(ref T fluent) where T : Fluent
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.ToList().FindAll(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
My problem is that calling "linqfluent.FlowCollection" in the linq method calls for the base class Fluent's FlowCollection, which is null.
How can I force the use of the child's property instead? Thanks!
You need to make the collection within Fluent generic so that the classes that inherit from it can specify the type:
public class Fluent<T>
where T : Flow
{
public IList<T> FlowCollection { get; set; }
public double InitialBaseflow { get; set; }
}
Once you have that you don't even need sub classes of Flow, you can just make it concrete.
Your use of it would be easily modified to fit this model:
private static void FindInitialBaseflow<T>(Fluent<T> fluent)
where T : Flow
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.Where(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
Also note that since you're not setting fluent in this method, there is no need to pass it by reference. It's already a class, so it is itself a reference; mutations of the referenced object will be observed by the caller.
Generics are the wrong tool. You should using polymorphism to ensure the correct implementation is called based on the type.
For example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApp
{
public abstract class Flow
{
public virtual double Value { get { return new Random().Next() ; } }//these values are just for demonstration purposes
public virtual DateTime Time
{
get
{
return DateTime.MinValue.AddYears(1);
}
}
}
public class InboundFlow : Flow
{
}
public class OutboundFlow : Flow
{
}
public abstract class Fluent
{
IList<Flow> _flowCollection;
public virtual IList<Flow> FlowCollection
{
get { return _flowCollection; }
set { _flowCollection = value; }
}
private double _initialBaseflow;
public virtual double InitialBaseflow
{
get { return _initialBaseflow; }
set { _initialBaseflow = value; }
}
public Fluent()
{
FlowCollection = new List<Flow>();
}
}
public class Affluent : Fluent
{
//public new virtual IList<InboundFlow> FlowCollection { get; set; }//Keep the property polymorphic
public Affluent()
{
FlowCollection = new List<Flow>();
}
}
public class Effluent : Fluent
{
//public new virtual IList<OutboundFlow> FlowCollection { get; set; }
public Effluent()
{
FlowCollection = new List<Flow>();
}
}
class Program
{
public static DateTime SOME_DATE { get { return DateTime.MinValue; } }
public static DateTime SOME_OTHER_DATE { get { return DateTime.Now; } }
static void Main(string[] args)
{
var inbound = new InboundFlow();
var inbound2 = new InboundFlow();
var outbound = new OutboundFlow();
var a = new Affluent();
a.FlowCollection.Add(inbound);
a.FlowCollection.Add(inbound2);
FindInitialBaseflow(a);
}
private static void FindInitialBaseflow(Fluent fluent)
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.ToList().FindAll(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
}
}
This is my problem:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public abstract class EntityMember<T>
{
public T Value { get; set; }
}
public class Int32EntityMember : EntityMember<int?>
{
}
public class StringEntityMember : EntityMember<string>
{
}
public class GuidEntityMember : EntityMember<Guid?>
{
}
public class Entity
{
public GuidEntityMember ApplicationId { get; private set; }
public Int32EntityMember ConnectedCount { get; private set; }
public GuidEntityMember MainApplicationId { get; private set; }
public Int32EntityMember ProcessId { get; private set; }
public StringEntityMember ProcessName { get; private set; }
}
class Program
{
static void Main(string[] args)
{
Entity entity2 = new Entity();
Guid empty = Guid.NewGuid();
Guid applicationId = Guid.NewGuid();
int Id = 10;
string name = "koko";
entity2.MainApplicationId.Value = new Guid?(empty);
entity2.ApplicationId.Value = new Guid?(applicationId);
entity2.ProcessId.Value = new int?(Id);
entity2.ProcessName.Value = name;
entity2.ConnectedCount.Value = 1;
}
}
}
The application has totally blocked on the line:
entity2.MainApplicationId. Value = new Guid? (empty);
Why?
The exception you're receiving is:
Object reference not set to an instance of an object.
This is because entity2.MainApplicationId is null. Your Entity class does not have a constructor to set MainApplicationId to be not null, hence the error you're seeing.
Adding a constructor to your Entity class as shown in the code below results in your code running without error:
public Entity()
{
ApplicationId = new GuidEntityMember();
ConnectedCount = new Int32EntityMember();
MainApplicationId = new GuidEntityMember();
ProcessId = new Int32EntityMember();
ProcessName = new StringEntityMember();
}
Using Auto-Implemented properties does not result in the underlying fields (that are created and managed on your behalf by the compiler) being new'd when the instance is constructed. Thus the two properties that follow are not the same:
public MyClass MyProperty { get; private set; }
private MyClass _myOtherProperty = new MyClass();
public MyClass MyOtherProperty
{
get
{
return _myOtherProperty;
}
set
{
_myOtherProperty = value;
}
}
Try changing the line to a type cast:
entity2.ApplicationId.Value = (Guid?)(applicationId);