I want to be able to do something like this:
IProcessDetails detailprocessor = MockRepository.GenerateMock();
detailprocessor.Expect(p => p.Process(null))
.Repeat.ForEachItemIn(details);
Here is the code I want to test
public class Detail
{
}
public class Master
{
public Master(IEnumerable<Detail> details)
{
Details = details;
}
public IEnumerable<Detail> Details { get; private set; }
}
public interface IProcessDetails
{
void Process(Detail detail);
}
public interface IProcessMasters
{
void Process(Master master);
}
public class MasterProcessor :
IProcessMasters
{
public MasterProcessor(IProcessDetails detailProcessor)
{
DetailProcessor = detailProcessor;
}
IProcessDetails DetailProcessor;
#region IProcessMasters Members
public void Process(Master master)
{
foreach (var detail in master.Details)
{
DetailProcessor.Process(detail);
}
}
#endregion
}
I want to verify that each detail is processed but only once and I'm not sure how to do it
Here is my current test:
public void GivenAMasterWithDetailsWhenProcessedThenAllDetailsAreProcessed()
{
IEnumerable<Detail> details = new List<Detail>()
{
new Detail(),
new Detail()
};
Master master = new Master(
details);
IProcessDetails detailprocessor = MockRepository.GenerateMock<IProcessDetails>();
//what I want or something similar
//detailprocessor.Expect(p => p.Process(null))
// .Repeat.ForEachItemIn(details);
//what it appears I can do
detailprocessor.Expect(p => p.Process(null))
.Constraints(List.OneOf(details))
.Repeat.Times(details.Count());
IProcessMasters masterprocessor = new MasterProcessor(
detailprocessor);
masterprocessor.Process(master);
detailprocessor.VerifyAllExpectations();
}
SOLVED -- I figured it out:
What I needed was a better understanding of rhino mocks.
Using a strict mock and a simple foreach loop solved the problem
here is my test now:
public void GivenAMasterWithDetailsWhenProcessedThenAllDetailsAreProcessed()
{
IEnumerable<Detail> details = new List<Detail>()
{
new Detail(),
new Detail()
};
Master master = new Master(
details);
IProcessDetails detailprocessor = MockRepository.GenerateStrictMock<IProcessDetails>();
foreach (var detail in details)
{
detailprocessor.Expect(p => p.Process(detail))
.Repeat.Once();
}
IProcessMasters masterprocessor = new MasterProcessor(
detailprocessor);
masterprocessor.Process(master);
detailprocessor.VerifyAllExpectations();
}
Related
I have one issue in subscribing to source cache. Let me describe the problem.
Lets say I have Test Class
public class Test {
public bool feature1 {get; set;} = false;
public bool feature2 {get; set; } = false;
public string name;
public Test(string name){
this.name = name
}
}
I want to see the changes happening in the property of test class and subscriber react according to change. But with current Implementation getting notification only when source is getting updated with new data not if any property of element in source cache is getting updated.
class Notifier {
public SourceCache<Test, string> testClassNotifier = new SourceCache<Test, string>(x => x.Name);
public Notifier(){
Task.Run(() =>
{
this.AddOrUpdateSourceCache();
this.SubscribeTestObj1();
this.SubscribeTestObj2();
}).ConfigureAwait(false);
}
private AddOrUpdateSourceCache()
{
List<Test> testListObj = new List<Test>() { new Test("test1"), new Test("test2") };
for (Test obj : testListObj) {
this.testClassNotifier.AddOrUpdate(obj);
}
Task.Run(async () => {
for(int i = 0; i<2; i++) {
this.testListObj[i].feature1 = true;
await Task.Delay(4000).ConfigureAwait(false);
// I want here to my get the notification in change with intial values as well.
}
}).ConfiguareAwait(false);
}
private IObservable<Test,string> GetNotification(string name){
// which api should use here ?? Or any way I can use `WhenAny` here.
return this.testClassNotifier.Watch(name);
}
private SubscribeTestObj1() {
this.GetNotification("test1").Subscribe(obj => // do something);
}
private SubscribeTestObj1() {
this.GetNotification("test2").Subscribe(obj => // do something);
}
}
One solution: implement INotifyPropertyChanged on the Test class, and use AutoRefresh()
Example:
public class Test : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
bool _feature1 = false;
public bool feature1
{
get => _feature1;
set
{
_feature1 = value;
PropertyChanged?.Invoke(this, new(nameof(feature1)));
}
}
// ... see the rest of the class in OP's question
}
Test:
var source = new SourceCache<Test, string>(x => x.name);
var a = new Test("a");
var b = new Test("b");
source
.Connect()
.AutoRefresh()
.Watch(b.name)
.Subscribe(change => Console.WriteLine($"Reason: <{change.Reason}> feature1: <{change.Current.feature1}>"));
source.AddOrUpdate(a);
source.AddOrUpdate(b);
b.feature1 = true;
Output:
Reason: <Add> feature1: <False>
Reason: <Refresh> feature1: <True>
I have a parent class called Snack with subclasses Drink and Sweets. I want to store my Snacks in a "VendingMachine" Class where there is a list for each of the Products. However, I don't want to write the same method for each type of Snack. How would you write this as a generic method ?
// DRINKS LIST
List<Drink> drinks = new List<Drink>();
public List<Drink> Drinks { get => drinks; set => drinks = value; }
private void FillWithProducts <Product> (params Product[] products) where Product : Snack
{
Type typeParameter = typeof(Product);
Type drink = typeof(Drink);
foreach (Product p in products)
{
if (typeParameter.Equals(drink))
{
Drinks.Add(p);
}
}
}
If you really need to store each kinds of products in theair own list, you can use a dynamically populated dictionary where the key is the type, something like this.
private readonly Dictionary<Type, List<Product>> storeByType = new();
public List<Drink> Drinks => (List<Drink>)this.storeByType[typeof(Drink)]
private void FillWithProducts<Product>(params Product[] products) where Product : Snack
{
foreach (Product p in products)
{
var key = p.GetType();
if (!this.storeByType.ContainsKey(key)) {
// ... add new List<T> instantiated by reflection
// use MakeGenericType + Activator.CreateInstance for example
}
// cast to the non-generic interface
var list = (IList)this.storeByType[key];
list.Add(p);
}
}
Note, that the code is just present as an example to demonstrate the idea, missing many checks and safety, and might not even work as is.
I would keep a dictionary inside the VendingMachine that holds the snacks of different types with the type as the key. By doing so you avoid having to search a list with mixed types every time you want to fetch the items.
static void Main(string[] args)
{
var m = new VendingMachine();
m.AddRange(new Drink(), new Drink());
m.AddRange(new Sweet());
var drinks = m.Fetch<Drink>();
var sweets = m.Fetch<Sweet>();
}
public class VendingMachine
{
private readonly Dictionary<Type, List<Snack>> _snacks = new();
public void AddRange<T>(params T[] snacks) where T : Snack
{
var type = typeof(T);
if (_snacks.TryGetValue(type, out var existingSnacks))
existingSnacks.AddRange(snacks);
else
_snacks.Add(type, new List<Snack>(snacks));
}
public List<T> Fetch<T>() where T : Snack
{
if (_snacks.TryGetValue(typeof(T), out var existingSnacks))
return new List<T>(existingSnacks.Cast<T>());
return new List<T>();
}
}
I think maybe there's a different way of doing this. With your base SnackBase base class and derived Drink and Sweet classes, you can fill a VendingMachine class with snacks then get the drink and sweet lists from the vending machine. The code below illustrates this:
Base Class
internal class SnackBase
{
public string Name { get; }
protected SnackBase(string name)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentOutOfRangeException(nameof(name));
Name = name;
}
}
Derived classes
internal class Drink : SnackBase
{
public Drink(string name) : base(name) {}
}
internal class Sweet : SnackBase
{
public Sweet(string name) : base(name) {}
}
VendingMachine.cs
internal class VendingMachine
{
private readonly List<SnackBase> _snacks;
public VendingMachine(List<SnackBase> snacks)
{
_snacks = snacks;
}
public List<SnackBase> GetDrinks()
{
return _snacks.Where(s => s.GetType().Name == nameof(Drink)).ToList();
}
public List<SnackBase> GetSweets()
{
return _snacks.Where(s => s.GetType().Name == nameof(Sweet)).ToList();
}
}
Program.cs
internal static class Program
{
public static void Main()
{
var snacks = new List<SnackBase>
{
new Drink("Coke"),
new Sweet("Snickers"),
new Drink("Pepsi"),
new Sweet("Mars Bar"),
new Drink("7 Up"),
new Sweet("Reece's Pieces")
};
var vendingMachine = new VendingMachine(snacks);
Console.WriteLine("Drinks");
Console.WriteLine("------");
var drinks = vendingMachine.GetDrinks();
foreach (var drink in drinks)
{
Console.WriteLine(drink.Name);
}
Console.WriteLine("Sweets");
Console.WriteLine("------");
var sweets = vendingMachine.GetSweets();
foreach (var sweet in sweets)
{
Console.WriteLine(sweet.Name);
}
}
}
The vending machine class only needs one list of the common type (Snack)
Snacks
public abstract class Snack
{
protected Snack(string name)
{
Name = name;
}
public string Name { get; }
public abstract override string ToString();
}
public class Sweet : Snack
{
public Sweet(string name) : base(name)
{
}
public override string ToString() => $"Sweet({Name})";
}
public class Drink : Snack
{
public Drink(string name) : base(name)
{
}
public override string ToString() => $"Drink({Name})";
}
Vending Machine
public class VendingMachine
{
readonly List<Snack> _snacks;
public VendingMachine(params Snack[] snacks) => _snacks = new List<Snack>(snacks);
public VendingMachine(IEnumerable<Snack> snacks) => _snacks = new List<Snack>(snacks);
public IReadOnlyList<Snack> Snacks { get => _snacks; }
public IReadOnlyList<Drink> Drinks { get => _snacks.OfType<Drink>().ToList(); }
public IReadOnlyList<Sweet> Sweets { get => _snacks.OfType<Sweet>().ToList(); }
public void AddDrink(string name) => _snacks.Add(new Drink(name));
public void AddSweet(string name) => _snacks.Add(new Sweet(name));
}
Test Program
static class Program
{
static void Main(string[] args)
{
var vend = new VendingMachine();
vend.AddDrink("Joke Cola");
vend.AddSweet("Mersa Bar");
vend.AddDrink("Diet Goo");
vend.AddDrink("Bronto Care");
vend.AddSweet("Broken Tooth");
Console.WriteLine("Vending Machine Sweets");
foreach (var item in vend.Sweets)
{
Console.WriteLine(item);
}
Console.WriteLine();
Console.WriteLine("Vending Machine Drinks");
foreach (var item in vend.Drinks)
{
Console.WriteLine(item);
}
}
}
Sample Output
Vending Machine Sweets
Sweet(Mersa Bar)
Sweet(Broken Tooth)
Vending Machine Drinks
Drink(Joke Cola)
Drink(Diet Goo)
Drink(Bronto Care)
I'm using a unity container and I'm trying to resolve by passing the object to the parameterized constructor, I noticed the same constructor is called twice, the first time it takes appropriate values, and not sure why it is calling again and it overrides with a blank object, can someone help me what is happening over here, not able to solve it.
//////////////////////////////////////////////////////////////////////
if (container == null)
{
container = new UnityContainer().AddExtension(new Diagnostic());
container.RegisterType<ISubscribeService,OOrderProc.Common.SubscribeService.SubscribeService>();
container.RegisterType<IBaseOrderProcessing, BaseSubscribe>("Subscribe");
}
SubscribeDetails m = new SubscribeDetails();
m.SubscribeType = SubscribeType.ACTIVATE;
m.SubscribeName = "TEST";
var b = container.Resolve<IBaseOrderProcessing>("Subscribe",new DependencyOverride<BaseSubscribe>(new OOrderProc.Common.SubscribeService.SubscribeService(m)));
//////////////////////////////////////////////////////////////////////
public interface IBaseOrderProcessing
{
void ProcessOrder();
}
public interface ISubscribeService
{
SubscribeType SubscribeType { get; set; }
void ActivateSubscribe();
void UpgradeSubscribe();
}
// Strategy Pattern 1 => Subscribe is one of the "if" condition
public class BaseSubscribe : IBaseOrderProcessing
{
private ISubscribeService _SubscribeService = null;
public BaseSubscribe(ISubscribeService SubscribeService)
{
_SubscribeService = SubscribeService;
}
public void ProcessOrder()
{
if (_SubscribeService.SubscribeType == SubscribeType.ACTIVATE)
_SubscribeService.ActivateSubscription();
if (_SubscribeService.SubscribeType == SubscribeType.UPGRADE)
_SubscribeService.UpgradeSubscription();
}
}
// Writing another class to simplify is correct ?????
public class SubscribeService : ISubscribeService
{
private SubscribeDetails _Subscribedetails = null;
public SubscribeType SubscribeType { get; set; }
public SubscribeService(SubscribeDetails Subscribedetails)
{
_Subscribedetails = Subscribedetails;
SubscribeType = Subscribedetails.SubscribeType;
}
public void ActivateSubscription()
{
// Code to save the Subscribe details in the database
Console.WriteLine($"\n\nSubscribe {_Subscribedetails.SubscribeId} for {_Subscribedetails.SubscribeName} activated for order Id: {_Subscribedetails.OrderId}" +
$" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");
}
public void UpgradeSubscription()
{
// Code to upgrade the Subscribe details in the database
Console.WriteLine($"\n\nSubscribe {_Subscribedetails.SubscribeId} for {_Subscribedetails.SubscribeName} upgraded for order Id: {_Subscribedetails.OrderId}" +
$" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");
}
}
I resolved using below code:
container.RegisterType<IBaseOrderProcessing, BaseSubscribe>("Subscribe", new InjectionConstructor(new OOrderProc.Common.SubscribeService.SubscribeService((SubscribeDetails)obj)));
return container.Resolve<IBaseOrderProcessing>("Subscribe");
I have a class that has an ICollection property that is assigned by the constructor when the class is instantiated, but I want to bind this property to the original collection so that when it's updated/changed, the original list is as well. What is the best method of doing this?
Here's an example:
public class Organizations
{
private ICollection<Organization> _orgs;
public Organizations(ICollection<Organization> orgs)
{
_orgs = orgs;
}
public void TestAdd()
{
_orgs.Add(new Organization {Name = "Testing 123"});
}
}
// in another class
public ActionResult TestApi()
{
var tmp = new SyncTool.Core.Extensions.Zendesk.Organizations(ZendeskCache.Organizations.Data);
var zd = ZendeskCache.Organizations.Data.FirstOrDefault(n => n.Name.Contains("Testing 123"));
//ZendeskCache.Org.... is a List<Organization>
return Json(new {data = "tmp" }, AG);
}
The List<Organization> you are passing to the constructor is a reference object. This code works the way you want it to (aside from syntax errors), have you tried it out?
To reproduce more simply:
public class Program
{
public static void Main(string[] args)
{
var orgs = new List<string>();
var orgClass = new Organizations(orgs);
orgClass.TestAdd();
Console.WriteLine(orgs.First());
Console.Read();
}
}
public class Organizations
{
private ICollection<string> _orgs;
public Organizations(ICollection<string> orgs)
{
_orgs = orgs;
}
public void TestAdd()
{
_orgs.Add("Testing 123");
}
}
//Output: "Testing 123"
I have an application which caches some data at startup. There are several things to put in a cache, but they are very similar. I created classes like this, the only difference in them is the type of the item to be added to the dictionary (in this example the Setting class), and the _sqlNotifyCommand.CommandText.
public class SettingsCache : ILoggerClass
{
private Dictionary<int, Dictionary<int, Setting>> _cachedItems;
private string _entityConnectionString;
private SQLNotifier _sqlNotifier;
private SqlCommand _sqlNotifyCommand = new SqlCommand();
private bool _dataLoaded = false;
private void AddItem(Setting item)
{
if (!_cachedItems.ContainsKey(item.PartnerId))
{
_cachedItems.Add(item.PartnerId, new Dictionary<int, Setting>());
}
if (_cachedItems[item.PartnerId].ContainsKey(item.Id))
{
_cachedItems[item.PartnerId].Remove(item.Id);
}
_cachedItems[item.PartnerId].Add(item.Id, item);
}
public Setting GetSetting(int partnerId, int id)
{
if (_cachedItems.ContainsKey(partnerId))
{
if (_cachedItems[partnerId].ContainsKey(id))
{
return _cachedItems[partnerId][id];
}
return null;
}
return null;
}
public SettingsCache(string connectionString)
{
_entityConnectionString = connectionString;
_cachedItems = new Dictionary<int, Dictionary<int, Setting>>();
LoadData();
try
{
using (var db = new partnerEntity(connectionString))
{
string adoSqlConnectionString = ((EntityConnection) db.Connection).StoreConnection.ConnectionString;
_sqlNotifier = new SQLNotifier(adoSqlConnectionString);
_sqlNotifier.NewMessage += _sqlNotifier_NewMessage;
_sqlNotifyCommand.CommandType = CommandType.Text;
_sqlNotifyCommand.CommandText = "SELECT setting_id, setting_value, partner_id FROM dbo.setting";
_sqlNotifyCommand.Notification = null;
_sqlNotifier.RegisterDependency(_sqlNotifyCommand);
}
}
catch (Exception exception)
{
this.Log(this, LogLevel.Error, 0, exception);
}
}
private void _sqlNotifier_NewMessage(object sender, SqlNotificationEventArgs e)
{
if (e.Info == SqlNotificationInfo.Insert || e.Info == SqlNotificationInfo.Update)
{
this.Log(this, LogLevel.Info, 0, string.Format("Database changed, reloading settings data..."));
LoadData();
}
_sqlNotifier.RegisterDependency(_sqlNotifyCommand);
}
private void LoadData()
{
_dataLoaded = false;
try
{
using (var db = new partnerEntity(_entityConnectionString))
{
var dbData = db.setting.ToList();
foreach (var cItem in dbData)
{
AddItem(new Setting
{
PartnerId = cItem.partner_id,
Id = cItem.setting_id,
Value = cItem.setting_value
});
}
}
_dataLoaded = true;
}
catch (Exception exception)
{
this.Log(this, LogLevel.Error, 0, exception);
}
if (!_dataLoaded)
{
Task.Delay(TimeSpan.FromSeconds(10)).ContinueWith(_ => { LoadData(); });
}
}
}
Is there a more generic way to do this? The last thing which was needed in the classes this part:
if (!_dataLoaded)
{
Task.Delay(TimeSpan.FromSeconds(10)).ContinueWith(_ => { LoadData(); });
}
And I had to modify every Caching class. I needed to declare the variable, add it to the try-catch block, and after the block insert the same line in 6 classes. This code seems very boilerplate to me, I can't believe there is no simpler solution. I tried to make an Interface with AddItem, LoadData, OnLoadDataFailed methods, but in the AddItem method I need to specify the item, I'm stuck.
Here is the basic structure of what (I think) you want to accomplish using Generics.
First, declare a common interface for cached items so that the AddItem method still works:
public interface ICacheItem
{
int Id { get; set; }
int PartnerId { get; set; }
}
Now you can create the SettingsCache<T> that holds the items:
public class SettingsCache<T> : ILogger where T : ICacheItem
{
private Dictionary<int, Dictionary<int, T>> _cachedItems;
//...
public SettingsCache(string connectionString, string commandText)
{
//...
}
private void AddItem(T item)
{
if (!_cachedItems.ContainsKey(item.PartnerId))
{
_cachedItems.Add(item.PartnerId, new Dictionary<int, T>());
}
if (_cachedItems[item.PartnerId].ContainsKey(item.Id))
{
_cachedItems[item.PartnerId].Remove(item.Id);
}
_cachedItems[item.PartnerId].Add(item.Id, item);
}
}
I left out most of the implementation to focus on your two biggest concerns, the command text and the AddItem method. The generic has a constraint so that it can only accept items that are of ICacheItem, so you can use any properties that ICacheItem defines.
To use a cache, simply create one with the specific type (assuming Setting implements ICacheItem):
var settingsCache = new SettingsCache<Setting>("connection string", "command string");