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?
Related
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)
};
}
}
Lets say I have something like the following.
namespace BurgerMachine
{
public class BaseList{
private static readonly List<Bases> bList = new List<Bases>() //might need to take off readonly
{
new Bases(){ BaseID=1, BaseName="Bun"},
new Bases(){ BaseID=2, BaseName="SeededBun"}
};
public static List<Bases> GetList()
{
return bList;
}
}
public class Bases
{
public int BaseID { get; set; }
public string BaseName { get; set; }
}
}
Now I would like to access the elements of the above list from another class, is this doable with my current setup or do I need to be returning more?
I have seen a few examples of people creating a List and then adding to from another class but not trying to access elements that already exist. If such an example does exist please point me in the right direction.
First time using Lists in this fashion so I'm not quite sure what I am doing. Any help would be great. If more information is needed please ask.
Here are few implementations best way to return list.
With static class
public class BaseListProvider
{
public static readonly Bases Bun = new Bases() { BaseID = 1, BaseName = "Bun" };
public static readonly Bases SeededBun = new Bases() { BaseID = 2, BaseName = "SeededBun" };
public static IEnumerable<Bases> GetList()
{
return new[]
{
Bun,
SeededBun
};
}
}
public class Bases
{
public int BaseID { get; set; }
public string BaseName { get; set; }
}
With interface which can be helpful if you are using dependency injection
public class BaseListProvider : IBaseListProvider
{
public static readonly Bases Bun = new Bases() { BaseID = 1, BaseName = "Bun" };
public static readonly Bases SeededBun = new Bases() { BaseID = 2, BaseName = "SeededBun" };
public IEnumerable<Bases> GetList()
{
return new[]
{
Bun,
SeededBun
};
}
}
public interface IBaseListProvider
{
IEnumerable<Bases> GetList();
}
public class Bases
{
public int BaseID { get; set; }
public string BaseName { get; set; }
}
Well you could just make the list a public member like below and access it from wherever you want
public List<Bases> bList = new List<Bases>()
{
new Bases(){ BaseID=1, BaseName="Bun"},
new Bases(){ BaseID=2, BaseName="SeededBun"}
};
You can access now saying
var blist = new BaseList().bList;
With your current setup (as already commented) why can't you just call the static method saying BaseList.GetList()
Main class:
public class Main
{
private string param;
public Main(string param) { this.param = param; }
public List<Foo> Foos
{
get {return GetFoos();}
// add functionality of saving Foo (single item, not the whole list) here?
}
private List<Foo> GetFoos()
{
List<Foo> x = new List<Foo>();
return x;
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
// or maybe here?
}
}
Test class:
public class Test
{
public Test()
{
var main = new Main("hi!");
// usage 1
main.Foos.Find(p => p.Id == 1).Save(); // method visible here
var foo = new Main.Foo();
// usage 2
foo.Save(); // method not visible here
}
}
Comments in the code basically say everything:
1. I want to implement the Save() method of the object Foo.
2. Method can be called only if the Foo object is picked up from the list (usage 1).
3. Method can not be called from the Foo object created alone (usage 2).
4. Method must use private value of the property param passed during initialization of the main class.
You can use an interface to hide the method Save.
To do this, the Save method must be implemented explicitly.
Additionally you need a link to the main object. In your subclass Foo you can access the private attribute from Main directly.
Interface:
public interface IFoo
{
int Id { get; set; }
string Name { get; set; }
void Save();
}
Class:
public class Main
{
private string param;
private List<IFoo> foos = new List<IFoo>();
public Main(string param) { this.param = param; }
public List<IFoo> Foos
{
get { return this.foos; }
}
public void AddFoo(int pnId, string pnName)
{
this.foos.Add(new Foo(this) { Id = pnId, Name = pnName });
}
public class Foo : IFoo
{
private Main moParent;
public Foo() { }
public Foo(Main poParent)
{
this.moParent = poParent;
}
public int Id { get; set; }
public string Name { get; set; }
//Implement interface explicitly
void IFoo.Save()
{
if (this.moParent == null)
throw new InvalidOperationException("Parent not set");
Console.WriteLine($"Save with Param: {this.moParent.param}, Id: {this.Id} Name: {this.Name}");
//Save Item
}
}
}
Usage:
var main = new Main("hi!");
main.AddFoo(1, "Foo1");
// usage 1
main.Foos.Find(p => p.Id == 1).Save(); // method visible here
var foo = new Main.Foo();
// usage 2
//foo.Save(); // Save is not visible here
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);
}
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);