How to write an Assert statement for collection in Xunit? - c#

I'm using an xUnit test framework to write some unit test. Below is a code snippet which test if azColumns collection is empty or not. However, I was thinking is there a better way to assert azColumns collection without using two Assert inside an if..else block statement?
Maybe a one liner Assert statement that makes sense?
private static string LoadJsonFile()
{
const string fileName = "templateFileContent_1.json";
var filePath = Path.Combine(Directory.GetCurrentDirectory(), $#"Data\{fileName}");
return !File.Exists(filePath) ? string.Empty : filePath;
}
private static string GetJsonData()
{
JObject jsonObject;
var jsonFile = LoadJsonFile();
if (string.IsNullOrEmpty(jsonFile)) return string.Empty;
using (var reader = new StreamReader(jsonFile))
{
var jsonData = reader.ReadToEnd();
jsonObject = JObject.Parse(jsonData);
}
return jsonObject.ToString();
}
private static JObject GetBaseConfigurationObject()
{
var json = GetJsonData();
if (string.IsNullOrEmpty(json)) return null;
var baseObject = JsonConvert.DeserializeObject<JObject>(json);
return baseObject;
}
[Fact]
public void ExportColumns_Should_Not_Be_Empty_Or_Null()
{
// Arrange
IEnumerable<az_Columns> azColumns = null;
// Act
var baseConfig = GetBaseConfigurationObject();
var fileContent = baseConfig?["templateFileContent"];
if (fileContent != null)
{
var baseConfiguration = fileContent.ToObject<BaseConfiguration>();
azColumns = baseConfiguration?.ExportData?.az_Columns;
}
// Assert
if (azColumns == null)
{
Assert.Null(azColumns);
}
else
{
Assert.NotEmpty(azColumns);
}
}
Any inputs is greatly appreciated.

If interested in using Fluent Assertions you can assert as follows
[Fact]
public void ExportColumns_Should_Not_Be_Empty_Or_Null() {
//Arrange
//...omitted for brevity
//Act
//..omitted for brevity
//Assert
azColumns.Should().NotBeNullOrEmpty();
}
After exercising your test you are asserting that the collection should not be null or empty. If it is null or empty the test will fail otherwise it will pass as expected.

Related

Cannot cast Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JToken

I'm new in C# and I'm writing API test. I need to write test which will create new user. Here it is:
public async Task CreatingNewUser_Returns200()
{
string client = BaseClass.mainURL;
var json = SettingsHelper.ReadSetting("NewUser");
httpc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(BaseClass.authKey, BaseClass.authValue);
var content = new StringContent(json);
var response = await httpc.PostAsync(client, content);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
Also, I have SettingsHelper class with two methods to make my json readable:
private static JObject _jObject;
public static string ReadSetting(string name)
{
var parts = name.Split('.', StringSplitOptions.RemoveEmptyEntries);
JToken token = GetObject();
foreach (var part in parts)
{
token = token[part];
if (token == null)
{
return null;
}
}
return token.Value<string>();
}
private static JObject GetObject()
{
if (_jObject != null)
{
return _jObject;
}
var filename = Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!,
"appsettings.json");
var json = File.ReadAllText(filename);
_jObject = JObject.Parse(json);
return _jObject;
}
And I have appsettings.json file with my user:
"NewUser": {
"externalDealId": "6051",
"Id": "12312111" // and so on
}
But when I launch this test I get an error (title name). How can I fix this?
Modify the code to
public static string ReadSetting(string name)
{
var parts = name.Split('.', StringSplitOptions.RemoveEmptyEntries);
JObject jObj= GetObject();
foreach (var part in parts)
{
var token = jObj[part];
if (token == null)
{
return null;
}
else
{
return token.ToString();
}
}
return null;
}
Actually, there is still a logic which needs to be noticed var parts = name.Split('.', StringSplitOptions.RemoveEmptyEntries); may mean that support multiple setting results. But logic in the ReadSetting function is not. It only return the first setting is matched.

Mock - Although setup .Returns(true) but always get false

I have code snippet as following. Although setup with retrurn true but value always return false.
Could someone advise how to retrieve value as true?
public interface IDatabaseService
{
bool ProcessSQL(INApplicationProcessDTO inApplicationProcessDTO, string connectionString, string storedProcedureName);
bool CompleteRun(INApplicationProcessDTO inApplicationProcessDTO, string connectionString, string storedProcedureName);
}
----CLASS----------
public static class INHelper
{
public static bool CompleteRun(INApplicationProcessDTO inApplicationProcessDTO, string connectionString = null, IDatabaseService databaseService = null)
{
if (inApplicationProcessDTO == null)
{
return false;
}
if (inApplicationProcessDTO.Data == null)
{
return false;
}
const string storedProcedureName = "PSP_PWS_INApplication_Application_Process_CompleteRun";
// Get Connection String to Parity4 Database from Parity4 WebService Web.config
if (connectionString == null)
{
if (ConfigurationManager.ConnectionStrings["ConnectionString"] != null)
{
connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
}
}
if (string.IsNullOrWhiteSpace(connectionString))
{
return false;
}
if (databaseService == null)
{
databaseService = new DatabaseService();
}
//Why always return false line below
return databaseService.CompleteRun(inApplicationProcessDTO, connectionString, storedProcedureName);
}
}
----TEST METHOD----
public void When_CompleteRun_ConnectionValid_Expect_True()
{
var iNApplicationProcessDTOTest = new INApplicationProcessDTO()
{
Data = new System.Xml.Linq.XDocument(),
ErrorCount = 0,
Errors = ""
};
Mock<IDatabaseService> iDatabaseService = null;
iDatabaseService = new Mock<IDatabaseService>();
iDatabaseService.Setup(t => t.CompleteRun(iNApplicationProcessDTOTest, "test", "test")).Returns(true);
iDatabaseService.Setup(t => t.ProcessSQL(iNApplicationProcessDTOTest, "test", "test")).Returns(true);
var iNApplicationProcessDTO = new INApplicationProcessDTO()
{
Data = new System.Xml.Linq.XDocument(),
ErrorCount = 0,
Errors = ""
};
var actual = INHelper.CompleteRun(iNApplicationProcessDTO, "a", iDatabaseService.Object);
//actual always false although Returns(true) in Setup
Assert.AreEqual(true, actual);
}
Appreciate your help.
There are a couple of tiny problems with your Test code.
First let me show how you should implement it and then let me give you some explanation:
[Fact]
public void GivenAFlawlessDatabaseService_WhenICallCompleteRun_ThenItCallsTheUnderlyingServicesCompleteRun()
{
//Arrange
const string connectionString = "a";
var iDatabaseService = new Mock<IDatabaseService>();
iDatabaseService
.Setup(db => db.CompleteRun(It.IsAny<INApplicationProcessDTO>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(true);
var iNApplicationProcessDTO = new INApplicationProcessDTO
{
Data = new XDocument(),
ErrorCount = 0,
Errors = ""
};
//Act
var actual = INHelper.CompleteRun(iNApplicationProcessDTO, connectionString, iDatabaseService.Object);
//Assert
Assert.True(actual);
iDatabaseService.Verify(db => db.CompleteRun(iNApplicationProcessDTO, connectionString, "PSP_PWS_INApplication_Application_Process_CompleteRun"), Times.Once);
iDatabaseService.Verify(db => db.ProcessSQL(It.IsAny<INApplicationProcessDTO>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
First, I would suggest to use somewhat more meaningful names for your tests. Here I've used a Given When Then structure to describe under what circumstances (given) if a specific action is triggered (when) what would I expect (then)
I also suggest to use the Arrange, Act and Assert comments to separate different phases of your test case visually
The Setup method calls normally do not rely on concrete objects. The reason behind it is that classes are compared by reference. So, even if you have two seemingly identical instances (like: iNApplicationProcessDTOTest and iNApplicationProcessDTO) they are different. That's why the mock function is not being called.
Use It.IsAny<T>() calls in the Setup phase and use concrete values in the Verify phase.
If one of the methods of the mocked object is not called by the SUT (system under test) then you don't need to Setup it.
But you can still verify that it has not been called (Verify(..., Times.Never);)

Unit test: Setup read/write Session variable using Moq

I have a function which based on some internal logic, stores a redirect string in a session variable (Redirect_To). I am trying to write a unit test which checks the value of this session variable once the action called has completed.
I am using Moq to mock up some of my properties and functions. However, whenever I set the Session variable (Redirect_To) up with Moq, it must set it as read only because I can no longer assign a value to it which leads my unit test to fail.
Here is my unit test:
public async Task Index_ClientTypeIsRPI_ExpectCorrectRedirect()
{
var sessionDict = new Dictionary<string, string>
{
{"CID", "124" },
{"UserName", "AK92630" },
{"REDIRECT_TO", "www.google.com" }
};
var controllerContext = HttpContextManager.ReturnMockControllerContextWithSessionVars(sessionDict);
var mockIdentity = new Mock<IIdentity>();
mockIdentity.Setup(x => x.Name).Returns("TestName");
controllerContext.Setup(x => x.HttpContext.User.Identity).Returns(mockIdentity.Object);
controllerContext.Setup(x => x.HttpContext.User.IsInRole(UserLevel.Subrep.GetDescription())).Returns(true);
controllerContext.Setup(x => x.HttpContext.Request.Browser.Browser).Returns("InternetExplorer");
_controller.ControllerContext = controllerContext.Object;
_iMockManifestManager.Setup(x => x.ReturnSingleMainDataRecordViaTransNoCIDAndUserNameAsync(It.IsAny<string>, It.IsAny<string>, It.IsAny<string>)).ReturnsAsync(New MainData());
var transNo = "Asdf";
await _controller.Index(transNo, true, "sd", "dg");
Assert.AreEqual("www.facebook.com", _controller.HttpContext.Session["REDIRECT_TO"]);
}
ReturnMockControllerContextWithSessionVars (Function which sets my session variables)
internal static Mock<ControllerContext> ReturnMockControllerContextWithSessionVars(Dictionary<string, object> sessionKeysAndValues):
{
var fakeHttpContext = HttpContextManager.CreateLocalAuthenticatedUserWithMockHttpContext();
var controllerContext = new Mock<ControllerContext>;
controllerContext.Setup(x => x.HttpContext).Returns(fakeHttpContext.Object);
foreach (var item in sessionKeysAndValues)
{
controllerContext.Setup(x => x.HttpContext.Session[item.Key]).Returns(item.Value);
}
return controllerContext;
}
Action:
public async Task Index(string transNo, bool? isRechase, string clientID, string clientType)
{
switch (clientType.ToUpper())
{
case "RPI":
Session["REDIRECT_TO"] = "www.reddit.com";
break;
case "LM":
Session["REDIRECT_TO"] = "www.bbc.co.uk";
default:
Session["REDIRECT_TO"] = "www.stackoverflow.com";
break;
}
//Do async stuff
return null;
}
Does anyone know how to change my code so when I setup Session["Redirect_To"] it remains read/write?
Also, I have converted this from VB.NET but I am fluent in both languages so if I have made any syntax errors it's from writing it free-hand. If that's the case, just let me know.
Thanks
Create a Stub to use for the session as moq will have difficulty setting up the collection used to hold values in the indexed property. The other dependencies should work as expected with moq.
class HttpSessionStateMock : HttpSessionStateBase {
private readonly IDictionary<string, object> objects = new Dictionary<string, object>();
public HttpSessionStateMock(IDictionary<string, object> objects = null) {
this.objects = objects ?? new Dictionary<string, object>();
}
public override object this[string name] {
get { return (objects.ContainsKey(name)) ? objects[name] : null; }
set { objects[name] = value; }
}
}
Using the example method under test from your original question base on "RPI" being the clientType the Following Test was exercised to completion and passed as expected.
[TestMethod]
public async Task Index_ClientTypeIsRPI_ExpectCorrectRedirect() {
//Arrange
var mock = new MockRepository(MockBehavior.Loose) {
DefaultValue = DefaultValue.Mock,
};
var session = new HttpSessionStateMock();//<-- session stub
var controllerContext = mock.Create<ControllerContext>();
controllerContext.Setup(_ => _.HttpContext.Session).Returns(session);
var _controller = new MyController() {
ControllerContext = controllerContext.Object
};
var transNo = "Asdf";
var clientID = "123";
var clientType = "RPI";
var sessionKey = "REDIRECT_TO";
var expected = "www.reddit.com";
//Act
await _controller.Index(transNo, true, clientID, clientType);
var actual = _controller.HttpContext.Session[sessionKey].ToString();
//Assert
Assert.AreEqual(expected, actual);
}

Mock method in Parallel.ForEach always returns null

I have the following code:
public int LoadFilesAndSaveInDatabase(string filesPath)
{
var calls = new ConcurrentStack<GdsCallDto>();
var filesInDirectory = this._directoryProxy.GetFiles(filesPath);
if (filesInDirectory.Any())
{
Parallel.ForEach(filesInDirectory, file =>
{
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
if (lines.Any())
{
// Reads the file and setup a new DTO.
var deserializedCall = this._fileManager.DeserializeFileContent(lines, Path.GetFileName(file));
// Insert the DTO in the database.
this._gdsCallsData.InsertOrUpdateGdsCall(deserializedCall);
// We keep track of the dto to count the number of restored items.
calls.Push(deserializedCall);
}
});
}
return calls.Count;
}
And I have the following unit test:
[TestMethod]
public void ShouldLoadFilesAndSaveInDatabase()
{
// Arrange
var path = RandomGenerator.GetRandomString(56);
var encoding = Encoding.Unicode;
var fileNameEnvironment = RandomGenerator.GetRandomString();
var fileNameModule = RandomGenerator.GetRandomString();
var fileNameRecordLocator = RandomGenerator.GetRandomString(6);
var fileNameTimestamp = RandomGenerator.GetRandomDateTime().ToString("O").Replace(':', 'o');
// We simulate the presence of 4 files.
var files = new List<string>
{
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255)
}.ToArray();
var expectedResult = 4;
this._directoryProxy.Expect(d => d.GetFiles(path))
.Return(files);
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
// Act
var result = this._databaseReloadManager.LoadFilesAndSaveInDatabase(path);
// Assert
Assert.AreEqual(result, expectedResult);
this._directoryProxy.AssertWasCalled(d => d.GetFiles(path));
this._fileProxy.AssertWasCalled(f => f.ReadAllLines(path, Encoding.Unicode));
}
The problem is on the following line:
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
Even though I set an expectation and a return value, when I run the unit test, it always returns null.
I am using Rhino.Mocks, it works perfectly fine elsewhere but not there.
I had a look at some discussions here but none of them helped. Can it be due to the use of Parallel.ForEach? Is there a way of doing such a mock?
If you need any other info, please let me know.
I don't think there is a problem with the Parallelization. It seems your problem is related to the proxy instance setup with Rhino Mock.
Ensure what you pass into the parameters of the ReadAllLines are the same as you call them when it run through the production code.
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
For instance if you setup on different path and the value of that path diefferent when test executes you may see NULL in return. But again hard to tell without seeing the full setup/constructor in the code. Also check the random generators see what has been used in each time.
The below is I sort of put together and working for me.
Working means I don't get NULL for:
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
//some dummy code so I can compile
public interface IProxyDir
{
IEnumerable<string> GetFiles(string path);
}
public class GdsCallDto
{
}
public class Proxy : IProxyDir
{
public IEnumerable<string> GetFiles(string path)
{
throw new NotImplementedException();
}
}
public interface IFileDir
{
IEnumerable<string> ReadAllLines(string path, Encoding encoding);
}
public class FileProxy : IFileDir
{
public IEnumerable<string> ReadAllLines(string path, Encoding encoding)
{
throw new NotImplementedException();
}
}
public interface IFileMgr
{
string DeserializeFileContent(IEnumerable<string> lines, string content);
}
public class FileMgr : IFileMgr
{
public string DeserializeFileContent(IEnumerable<string> lines, string content)
{
throw new NotImplementedException();
}
}
//system under test
public class Sut
{
private IProxyDir _directoryProxy;
private IFileDir _fileProxy;
private IFileMgr _fileManager;
public Sut(IProxyDir proxyDir, IFileDir fileProxy, IFileMgr mgr)
{
_fileManager = mgr;
_directoryProxy = proxyDir;
_fileProxy = fileProxy;
}
public int LoadFilesAndSaveInDatabase(string filesPath)
{
var calls = new ConcurrentStack<GdsCallDto>();
var filesInDirectory = this._directoryProxy.GetFiles(filesPath);
if (filesInDirectory.Any())
{
Parallel.ForEach(filesInDirectory, file =>
{
var lines = this._fileProxy.ReadAllLines("ssss", Encoding.Unicode);
if (lines.Any())
{
// Reads the file and setup a new DTO.
var deserializedCall = this._fileManager.DeserializeFileContent(lines, Path.GetFileName("file"));
// Insert the DTO in the database.
//this._gdsCallsData.InsertOrUpdateGdsCall(deserializedCall);
// We keep track of the dto to count the number of restored items.
//calls.Push(deserializedCall);
}
});
}
return 1;
}
}
Sample Unit Test
[TestClass]
public class UnitTest1
{
private IProxyDir _directoryProxy;
private IFileDir _fileProxy;
private IFileMgr _fileMgr;
private Sut _sut;
public UnitTest1()
{
_directoryProxy = MockRepository.GenerateMock<IProxyDir>();
_fileProxy = MockRepository.GenerateMock<IFileDir>();
_fileMgr = MockRepository.GenerateMock<IFileMgr>();
}
[TestMethod]
public void ShouldLoadFilesAndSaveInDatabase()
{
// Arrange
var path = RandomGenerator.GetRandomString(56);
var encoding = Encoding.Unicode;
var fileNameEnvironment = RandomGenerator.GetRandomString(5);
var fileNameModule = RandomGenerator.GetRandomString(5);
var fileNameRecordLocator = RandomGenerator.GetRandomString(6);
var fileNameTimestamp = RandomGenerator.GetRandomDateTime().ToString("O").Replace(':', 'o');
// We simulate the presence of 4 files.
var files = new List<string>
{
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255)
}.ToArray();
var expectedResult = 4;
this._directoryProxy.Expect(d => d.GetFiles(path))
.Return(files);
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
_sut = new Sut(_directoryProxy, _fileProxy, _fileMgr);
// Act
var result = this._sut.LoadFilesAndSaveInDatabase(path);
// Assert
Assert.AreEqual(result, expectedResult);
this._directoryProxy.AssertWasCalled(d => d.GetFiles(path));
this._fileProxy.AssertWasCalled(f => f.ReadAllLines(path, Encoding.Unicode));
}
}
internal class RandomGenerator
{
public static string GetRandomString(int number)
{
return "ssss";
}
public static DateTime GetRandomDateTime()
{
return new DateTime();
}
}
I could get rid of this issue, probably caused by the use of random values. I am now calling the method IgnoreArguments() on my expectation:
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length).IgnoreArguments();
It does the trick (i.e. the unit test is running successfully), but I do not know if it is very elegant.

If chained - how to delete?

I'm doing an application where I have the following scenario:
I have several rules (business classes)
where they all return the client code. They are separate classes that will look for the code trial and error, if find the client code returns it and so on.
How can I use a rule without using a bunch of IFs or threaded IFs in the class that calls the others that contains the specific business rules?
For the specific classes, I used the design pattern strategy.
EX: Main Class
public abstract class Geral
{
public abstract string retornaCodigo(Arquivo cliente)
{
var codigo = ""; // logica
return codigo;
}
}
public class derivada1 : Geral
{
public override string retornaCodigo(Arquivo cliente)
{
var codigo = ""; // logica
return codigo;
}
}
public class derivada2 : Geral
{
public override string retornaCodigo(Arquivo cliente)
{
var codigo = ""; // logica 2
return codigo;
}
}
public class derivada3 : Geral
{
public override string retornaCodigo(Arquivo cliente)
{
var codigo = ""; // logica 3
return codigo ;
}
}
public class Negocio
{
public string Codigo()
{
var arquivo = new Arquivo();
var derivada1 = new derivada1().retornaCodigo(arquivo);
var derivada2 = new derivada2().retornaCodigo(arquivo);
var derivada3 = new derivada3().retornaCodigo(arquivo);
if (derivada1.Equals(null))
return derivada1;
if (derivada2.Equals(null))
return derivada2;
if (derivada3.Equals(null))
return derivada3;
return "";
}
}
what I wanted and that I did not have to use Ifs in the Business class for validation whether or not I found the code where it can fall under any condition gave example of 3 classes plus I have more than 15 conditions and can increase, case would be many Ifs.
Let's organize all derivada into a collection, say, array and then query the collection with a help of Linq
public string Codigo() {
var arquivo = new Arquivo();
Geral[] derivadas = new [] {
new derivada1(),
new derivada2(),
new derivada3();
};
//TODO: check the the condition: I guessed that you want to return first meanful codigo
foreach (var codigo in derivadas.Select(geral => geral.retornaCodigo(arquivo)))
if (!string.IsNullOrEmpty(codigo))
return codigo;
return "";
}
If you have a lot of derivada you can try using Reflection in order to create a collection:
using System.Reflection;
...
private static Geral[] s_Derivadas = AppDomain
.CurrentDomain
.GetAssemblies() // scan assemblies
.SelectMany(asm => asm.GetTypes()) // types within them
.Where(t => !t.IsAbstract) // type is not abstract
.Where(t => typeof(Geral).IsAssignableFrom(t)) // type derived from Geral
.Where(t => t.GetConstructor(Type.EmptyTypes) != null) // has default constructor
.Select(t => Activator.CreateInstance(t) as Geral) // create type's instance
.ToArray(); // materialized as array
then
public string Codigo() {
var arquivo = new Arquivo();
foreach (var codigo in s_Derivadas.Select(geral => geral.retornaCodigo(arquivo)))
if (!string.IsNullOrEmpty(codigo))
return codigo;
return "";
}
You could create a list of derivada's and then iterate over it
and if any given derivada1 equals None, you simply return it, otherwise you just continue the 'for loop'
I could write up a snippet if this doesn't make sense to you. lmk!
This would be simple with Linq:
public class Negocio
{
public string Codigo()
{
var arquivo = new Arquivo();
var derivadaList = new List<Geral>() {
new derivada1(),
new derivada2(),
new derivada3(),
};
return derivadaList.FirstOrDefault(d => d.retornaCodigo(arquivo) == null)?.retornaCodigo(arquivo) ?? "";
}
}
You can add as many Geral derived classes to the derivadaList as you want and the code will continue to function as designed.
What is happening here is that FirstOrDefault will run the Lamda expression on every element returning the first one that equals null (although I'm not sure this is what you want, it matches your example code). Since it returns a Geral object, you need to call retornaCodigo on it only if it is not null. If it is null, just return an empty string.
Another way to write this would be:
public class Negocio
{
public string Codigo()
{
var arquivo = new Arquivo();
var derivadaList = new List<Geral>() {
new derivada1(),
new derivada2(),
new derivada3(),
};
foreach (var derivada in derivadaList)
{
var result = derivada.retornaCodigo(arquivo);
if (result == null)
return result;
}
return "";
}
}
You can also use a list of derived classes and call them in Loop
public string Codigo()
{
var arquivo = new Arquivo();
List<Geral> gerals=new List<Geral>();
gerals.Add(new derivada1());
gerals.Add(new derivada2());
........
...........
foreach(Geral g in gerals)
{
var val=g.retornaCodigo(arquivo);
if(val!=null)
return val;
}
return "";
}
This is a sample implementation, However you are not using strategy correctly
A better approach will be constructor injection,
public string Codigo(Geral implementar)
{
var val=geral.retornaCodigo(arquivo);
return "";
}
Then instantiate only with the chosen strategy.
Otherwise if you want to chain multiple validations, then use CHain of responsibility pattern.

Categories

Resources