FakeItEasy VB.NET issues with parameters - vb.net

Ok, I am trying to teach myself testing using a mock framework and I work in VB.NET, I am new to lambda expressions and all my previous applications were written in version 2005 or earlier. I now have 2010.
So I have tried Rhino.Mocks but found it difficult to get my head around it mostly because of the older syntax. Since, no-one seems to be bloggin in VB.NET these days, I have been looking at C# examples and trying to figure out what is going on.
So I have a situation where I pass an interface to the constructor of a class and hold a refrence to that interface. When an method is called on the object and event is raise that should be handled by the class that implements the inteface.
I was having trouble, so I tried to create a simple version in C# and repeat the steps in vb.net.
So my interface:
public interface IBroadcastClient
{
void MessageReceivedHandler(string msg);
}
The class that raises the events:
public class Broadcaster
{
public Broadcaster(IBroadcastClient c)
{
_client= c;
this.SendMessage += new MessageReceived(_client.MessageReceivedHandler);
}
private IBroadcastClient _client;
public event MessageReceived SendMessage;
public void SendMessageNow()
{
string _Message;
if (SendMessage != null)
{
_Message = #"Yay!";
SendMessage(_Message);
}
}
}
The test:
[TestMethod]
public void TestSendMessageWithIgnoreParameter()
{
//string msg = #"Yay!";
var client = A.Fake<IBroadcastClient>();
Broadcaster b = new Broadcaster(client);
b.SendMessageNow();
A.CallTo(() => client.MessageReceivedHandler(A<string>.Ignored)).MustHaveHappened();
}
This passes, no problems so far.
Now to try the same this in vb.net;
The same interface and broadcaster class, just in vb.net rather than C# with initially hte following unit test.
<TestMethod()>
Public Sub TestMethod1()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).MustHaveHappened()
client.MessageReceivedHandler(A(Of String).Ignored)
End Sub
This fails with the following error message;
" Assertion failed for the following call:
TestFakeItEasyVB.IBroadcastClient.MessageReceivedHandler(msg: )
Expected to find it at least once but found it #0 times among the calls:
1: TestFakeItEasyVB.IBroadcastClient.MessageReceivedHandler(msg: "Yay!")"
Funnily enough writing it this way;
<TestMethod()>
Public Sub TestMethod3()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
A.CallTo(Sub() client.MessageReceivedHandler(A(Of String).Ignored)).MustNotHaveHappened()
End Sub
Will also fail with the same error message, however, this version of the test passes.
<TestMethod()>
Public Sub TestMethod2()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).MustHaveHappened()
client.MessageReceivedHandler("Yay!")
End Sub
This variation also passes in C#, my quandry is what am I doing wrong to get the test to ignore the argument passed to the faked event handler?

The NextCall-syntax is there for legacy reasons, it's better to use the expression syntax:
A.CallTo(Sub() client.MessageReceivedHandler(A(Of String).Ignored)).MustNotHaveHappened()
In your tests above all others has MustHaveHappened, but this specific one has MustNotHaveHappened, I guess that's why your test is failing. I've compiled your code and run it and once it's changed to MustHaveHappened the test passes.
Currently you can not use argument constraints in the VB-specific "NextCall"-syntax. However you can use the method "WhenArgumentsMatch" to rewrite your first test like this:
<TestMethod()>
Public Sub TestMethod1()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).WhenArgumentsMatch(Function(a) a.Get(Of String)(0) = "Yay!").MustHaveHappened()
client.MessageReceivedHandler(Nothing)
End Sub
Or you could use the extension "WithAnyArguments" to ignore all arguments:
<TestMethod()>
Public Sub TestMethod1()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).WithAnyArguments().MustHaveHappened()
client.MessageReceivedHandler(Nothing)
End Sub

Related

Call instance method inline after New statement

How can i convert this code to VB.net
public void SetBooks(IEnumerable<Book> books)
{
if (books == null)
throw new ArgumentNullException("books");
new System.Xml.Linq.XDocument(books).Save(_filename);
}
in http://converter.telerik.com/ it says:
Public Sub SetBooks(books As IEnumerable(Of Book))
If books Is Nothing Then
Throw New ArgumentNullException("books")
End If
New System.Xml.Linq.XDocument(books).Save(_filename)
End Sub
But visual studio says "Syntax error." because of "New"
What is the keyword for this situation, i searched on Google but no result.
Actually, you can do it in one line with the Call keyword
Call (New System.Xml.Linq.XDocument(books)).Save(_filename)
You cannot initialize an object and use it in one statement in VB.NET (as opposed to C#). You need two:
Dim doc = New System.Xml.Linq.XDocument(books)
doc.Save(_filename)
In C# the constructor returns the instance of the created object, in VB.NET not.

Best method for initializling the Okuma API if I want a program that works for both lathe and mills?

I am writing a program that will run on both lathe and machining centers. How best can I initialize the API without doing during loading. Should I call a class for each machine type or can I call each (and close them) within the same class?
Added example of current method for just Lathe...
using Okuma.CLDATAPI.DataAPI;
using Okuma.CLDATAPI.Enumerations;
using Okuma.CLDATAPI.Structures;
using Okuma.CLDATAPI.DataAPI.MacMan;
public class LatheDutyOnline
{
private CMachine Objl;
private CVariables Objlv;
private CIO IO;
private CATC ObjAtc;
private CAxis objaxis;
private CBallScrew objBS;
private CProgram objProgram;
private CSpec objSpec;
private CSpindle objSpindle;
private void Form1_Load(System.Object sender, System.EventArgs e)
{
Objl = new CMachine();
Objl.Init();
Objlv = new CVariables();
IO = new CIO();
ObjAtc = new CATC();
objaxis = new CAxis();
objBS = new CBallScrew();
objProgram = new CProgram();
objSpec = new CSpec();
objSpindle = new CSpindle();
}
You need a routine to check the current machine type. Something like this:
Private Sub CheckMachineType()
If System.IO.File.Exists("C:\OSP-P\SHAREDDLL\LDATAPI.DLL") And System.IO.File.Exists("C:\OSP-P\VOLANTE\CRAD\LCMDAPI.EXE") Then
MachineType = Lathe
ElseIf System.IO.File.Exists("C:\OSP-P\SHAREDDLL\MDATAPI.DLL") And System.IO.File.Exists("C:\OSP-P\VOLANTE\CRAD\MCMDAPI.EXE") Then
MachineType = MachiningCenter
Else
MachineType = NonOSP
End If
End Sub
Then you can initialize the correct API type based on the value of MachineType.
UPDATE
We now have a standard machine agnostic library that is perfect for this.
Please have a look at the sample program for SCOUT.
https://github.com/OkumaAmerica/Open-API-SDK/tree/master/Scout
Take a look at c# intro to Interfaces and this video using .Net interfaces for machine neutral applications. Using interfaces allows you to program against the interface instead of directly against the API.

could not run this unit test with mock

I tried to make an unit test for this method which is pretty simple only add an object into the data base and if it works well returns true
Public Shared Function CrearCliente(ByVal cliente As Cliente) As Boolean
Try
db.Cliente.Add(cliente)
db.SaveChanges()
Return True
Catch ex As Exception
Throw New Exception("ocurrio un error guardando al cliente")
End Try
End Function
Now here's my test
<TestMethod()>
Public Sub CrearClienteTest()
Dim mock = New Moq.Mock(Of Cliente)
Dim actual As Boolean
mock.Setup(Function(x) x.Nombre).Returns("blah")
'mock.Setup(Function(x) x.Apellido()
actual = Class1.CrearCliente(mock.Object)
Assert.AreEqual(True, actual)
End Sub
Pretty easy my question is why when Debugged the test throws this error
Invalid setup on a non-virtual (overridable in VB) member: x => x.Nombre
What could be wrong? do i need another configuration?
As the error states, Moq requires that the member you mock be Overridable.

Iterator pattern in VB.NET (C# would use yield!) [duplicate]

This question already has answers here:
Yield in VB.NET
(8 answers)
Closed 9 years ago.
How do implement the iterator pattern in VB.NET, which does not have the yield keyword?
This is now supported in VS 2010 SP1, with the Async CTP, see: Iterators (C# and Visual Basic) on MSDN and download Visual Studio Async CTP (Version 3).
Code such as this, works:
Private Iterator Function SomeNumbers() As IEnumerable
' Use multiple yield statements.
Yield 3
Yield 5
Yield 8
End Function
VB.NET does not support the creation of custom iterators and thus has no equivalent to the C# yield keyword. However, you might want to look at the KB article How to make a Visual Basic .NET or Visual Basic 2005 class usable in a For Each statement for more information.
C#'s yield keyword forces the compiler to create a state machine in the background to support it. VB.Net does not have the yield keyword. But it does have a construct that would allow you to create a state machine within a function: Static function members.
It should be possible to mimic the effects of a yield return function by creating a generic class that implements IEnumerable as well as the needed state machine and placing an instance as a static member inside your function.
This would, of course, require implementing the class outside of the function. But if done properly the class should be re-usable in the general case. I haven't played with the idea enough to provide any implementation details, though.
Hmm, looks like you might be out of luck:
I was struggling with an issue today when converting some C# to VB.NET. C# has a really cool "yield return" statement that is used in an iterator block to provide a value to the enumerator object. VB.NET does not have the "yield" keyword. So, there are a few solutions (none of which are really clean) to get around this. You could use a return statement to return the value if you are looping through and would like to break an enumerator and return a single value. However, if you'd like to return the entire enumeration, create a List() of the child type and return the list. Since you are usually using this with an IEnumerable, the List() will work nice.
That was written a year ago, not sure if anyone has come up with anything else better since then..
Edit: this will be possible in the version 11 of VB.NET (the one after VS2010), support for iterators is planned. The spec is available here.
Keep in mind that deferred execution and lazy evaluation properties of LINQ expresssions and methods allow us to effectively implement custom iterators until the yield statement is available in .NET 4.5. Yield is used internally by LINQ expressions and methods.
The following code demonstrates this.
Private Sub AddOrRemoveUsersFromRoles(procName As String,
applicationId As Integer,
userNames As String(),
rolenames As String())
Dim sqldb As SqlDatabase = CType(db, SqlDatabase)
Dim command As DbCommand = sqldb.GetStoredProcCommand(procName)
Dim record As New SqlDataRecord({New SqlMetaData("value", SqlDbType.VarChar,200)})
Dim setRecord As Func(Of String, SqlDataRecord) =
Function(value As String)
record.SetString(0, value)
Return record
End Function
Dim userNameRecords As IEnumerable(Of SqlDataRecord) = userNames.Select(setRecord)
Dim roleNameRecords As IEnumerable(Of SqlDataRecord) = rolenames.Select(setRecord)
With sqldb
.AddInParameter(command, "userNames", SqlDbType.Structured, userNameRecords)
.AddInParameter(command, "roleNames", SqlDbType.Structured, roleNameRecords)
.AddInParameter(command, "applicationId", DbType.Int32, applicationId)
.AddInParameter(command, "currentUserName", DbType.String, GetUpdatingUserName)
.ExecuteNonQuery(command)
End With
End Sub
Below gives output: 2, 4, 8, 16, 32
In VB.NET
Public Shared Function setofNumbers() As Integer()
Dim counter As Integer = 0
Dim results As New List(Of Integer)
Dim result As Integer = 1
While counter < 5
result = result * 2
results.Add(result)
counter += 1
End While
Return results.ToArray()
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
For Each i As Integer In setofNumbers()
MessageBox.Show(i)
Next
End Sub
In C#
private void Form1_Load(object sender, EventArgs e)
{
foreach (int i in setofNumbers())
{
MessageBox.Show(i.ToString());
}
}
public static IEnumerable<int> setofNumbers()
{
int counter=0;
//List<int> results = new List<int>();
int result=1;
while (counter < 5)
{
result = result * 2;
counter += 1;
yield return result;
}
}

How do I unit test object serialization/deserialization in VB.NET 1.1?

I am looking for example code that provides a unit test to serialize and deserialize an object from a memory stream. I have found examples using C# 2.0, however my current project uses VB.NET 1.1 (don't ask me why...), so the solution can not use generics. I am also using the NUnit framework for the unit tests.
Thanks!
This is the pattern I've settled upon:
<Test()> _
Public Sub SerializationTest()
Dim obj As New MySerializableObject()
'Perform additional construction as necessary
Dim obj2 As MySerializableObject
Dim formatter As New BinaryFormatter
Dim memoryStream As New MemoryStream()
'Run through serialization process
formatter.Serialize(memoryStream, obj)
memoryStream.Seek(0, SeekOrigin.Begin)
obj2 = DirectCast(formatter.Deserialize(memoryStream), MySerializableObject)
'Test for equality using Assert methods
Assert.AreEqual(obj.Property1, obj.Property1)
'etc...
End Sub
NUnit has built in support for this which makes it quite a bit easier:
Dim obj As New MySerializableObject()
Assert.That(obj, Is.BinarySerializable)
Or for xml:
Dim obj As New MySerializableObject()
Assert.That(obj, Is.XmlSerializable)
If all you want to do is to ensure that they are serializable then all you should have to do it to do a serialization of an object and make sure no XmlSerializationException was thrown
[Test]
public void ClassIsXmlSerializable()
{
bool exceptionWasThrown = false;
try
{
// .. serialize object
}
catch(XmlSerializationException ex)
{
exceptionWasThrown = true;
}
Asset.IsFalse(exceptionWasThrown, "An XmlSerializationException was thrown. The type xx is not xml serializable!");
}
Hmm...so you are trying to write a unit test for serialization? Or for streams? This is hopefully done by MS already...but if you don't trust or implement something on your own...you could just fill object with some data, save it, restore it, and check if the fields values are in place?