I have an interface that includes a member that looks like:
void ExecuteSqlCommand(string procedureName, SqlParameter[] parameters);
I am using FakeItEasy to create a mock of this to pass to one of my classes.
The code I am testing calls this method, then checks the value of one of the SqlParameters. How do I use FakeItEasy to set the Value property of this parameter when the method is called?
I appreciate that this is probably not the best practice for getting individual pieces of information out of a database, but I am working with existing stored procedures, some of which have OUT parameters.
As you say, this is probably not the best practice. That aside, I guess you could do something like this:
A.CallTo(() => fake.ExecuteSqlCommand(A<string>._, A<SqlParameter[]>._))
.Invokes((string s, SqlParameter[] p) => p[someIndex].Value = yourValue);
Or, using a less-readable but more powerful overload, access a IFakeObjectCall directly:
A.CallTo(() => fake.ExecuteSqlCommand(A<string>._, A<SqlParameter[]>._))
.Invokes(callObject => callObject.GetArgument<SqlParameter[]>("parameters")[someIndex].Value = yourValue);
Related
I am using entity framework and I want to execute a query and would like to know which is the besr way to execute a query. Which is best practice and why, and which one is more per-formant.
Option 1)
return
this.Storage.Customer.OfType<Preferred>()
.Include("Order")
.Where("it.Id = #customerId AND it.CustomerType = #cusType", new ObjectParameter("customerId ", customerId), new ObjectParameter("cusType", (int)cusType))
.Execute(MergeOption.OverwriteChanges)
.SingleOrDefault();
OR
return
this.Storage.Customer.OfType<Preferred>()
.Include(b => b.Order)
.Where(cust => cust.Id == customerId && cust.CustomerType== (int)cusType)
.SingleOrDefault();
The second question is why in option 2 us the .Execute not available? It appears red.
Thanks in advance.
The performance difference should be negligible compared with the actual data access, but you need to measure it to determine for sure.
Include with a lambda just uses reflection to get the property name then calls the version with a string parameter, so the only overhead is parsing the expression. (This is an implementation detail, however, so it is subject to change)
The benefit of using a lambda is type safety - using the wrong property name in a lambda will break the build, but using the wrong string will only fail at run-time.
The reason Execute is not available is because Include with a lambda parameter is an extension method on IQueryable<T> that returns an IQueryable<T> in order to chain methods like Where. Include with a string parameter is a method on ObjectQuery<T> that returns an ObjectQuery<T>. Execute is a method on ObjectQuery<T>, not IQueryable<T> so it is not available when you use IQueryable methods.
I just started to use DBx::Class and begun slightly to understand, but it's complex.
I want to call "recursive_update" but I was not able to manage how I can use it.
If I understand the documentation right, I have to include it in the .../My/Schema.pm which was create by DBIx::Class::Schema::Loader?
__PACKAGE__->load_namespaces(default_resultset_class => '+DBIx::Class::ResultSet::RecursiveUpdate');
When I want to update the data I use the ResultSet with the relationships.
my $result = $schema->resultset('Table')->find($id});
$result->recursive_update({
'rel_table' => [....),
});
unfortunately I got an error:
Can't locate object method "recursive_update" via package My::Schema::Result::Table"
Where is my fault?
recursive_update has to be called on a ResultSet object, not a Result object.
You might want to add a helper method to your Result base class (if you already have one else create it, as it makes sense for many things) which gets a ResultSet restricted to the Result object it is called on and calls recursive_update on it.
I'm trying to use FakeItEasy 2.0.0 to fake a property in a simple interface:
public interface IPerson
{
int Age { set; }
}
Note that I don't have a get accessor. The test I'm trying to write is:
public void SetsAge()
{
var fakePerson = A.Fake<IPerson>();
A.CallToSet(() => fakePerson.Age).To(42).MustHaveHappened();
fakePerson.Age = 42;
}
But the line containing A.CallToSet fails to compile with:
which is fairly self-explanatory, but confusing since I'm not trying to get the property's value.
Do I have to provide a get accessor to get this to compile (even though I don't want a get accessor)? What is the reason that it requires the get accessor in this case (the same compiler error happens when I replace MustHaveHappened with DoesNothing)? Or am I doing something fundamentally wrong?
Or perhaps I shouldn't lose too much sleep over this and do the right thing in the first place?
Do I have to provide a get accessor to get this to compile?
No, you can use
A.CallTo(fakePerson).Where(call => call.Method.Name == "set_Age" &&
call.GetArgument<int>(0) == 42)
.MustHaveHappened();
This is documented in Specifying a call to any method or property.
What is the reason that it requires the get accessor?
The reason is that because you can't use a = in a lamdba expression, there's no easy way to refer to the property setter. In 2.0, we added A.CallToSet to allow you to cheat by using the getter, but of course it only works when there is a getter.
We've not yet come up with an elegant way to refer to a getterless setter, so you have to use the powerful version of A.CallTo above.
Or am I doing something fundamentally wrong?
Well, in addition to the problem with referring to the property, the whole A.CallTo…MustHaveHappend() has to occur after fakePerson.Age = 42, or it will report a failure, because you haven't yet set fakePerson.Age to 42.
Am having a little trouble understanding what and what cannot be done using FakeItEasy. Suppose I have a class
public class ToBeTested{
public bool MethodToBeTested(){
SomeDependentClass dependentClass = new SomeDependentClass();
var result = dependentClass.DoSomething();
if(result) return "Something was true";
return "Something was false";
}
}
And I do something like below to fake the dependent class
var fakedDepClass = A.Fake<DependentClass>();
A.CallTo(fakedDepClass).WithReturnType<bool>().Returns(true);
How can i use this fakedDepClass when am testing MethodToBeTested. If DependentClass was passed as argument, then I can pass my fakedDepClass, but in my case it is not (also this is legacy code that I dont control).
Any ideas?
Thanks
K
Calling new SomeDependentClass() inside MethodToBeTested means that you get a concrete actual SomeDependentClass instance. It's not a fake, and cannot be a FakeItEasy fake.
You have to be able to inject the fake class into the code to be tested, either (as you say) via an argument to MethodToBeTested or perhaps through one of ToBeTested's constructors or properties.
If you can't do that, FakeItEasy will not be able to help you.
If you do not have the ability to change ToBeTested (and I'd ask why you're writing tests for it, but that's an aside), you may need to go with another isolation framework. I have used TypeMock Isolator for just the sort of situation you describe, and it did a good job.
I have this code in my project, how can I use Moq to moq the documentsession and setup the return value?
_session.Query<IPageModel, PageByUrl>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(x => x.Metadata.Url == virtualUrl);
This is what I have tried before I asked
var session = new Mock<IDocumentSession>();
var pageModel = new DummyModel();
session.Setup(x => x.Query<IPageModel, PageByUrl>()
.Customize(y => y.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(y => y.Metadata.Url == path)).Returns(pageModel);
This throws an exception and I can't figure out how to change the moq
System.NotSupportedException : Expression references a method that does not belong to the mocked object: x => x.Query<IPageModel,PageByUrl>().Customize(y => y.WaitForNonStaleResultsAsOfLastWrite()).FirstOrDefault<IPageModel>(y => y.Metadata.Url == .path)
at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b()
at Moq.Mock.Setup(Mock mock, Expression`1 expression, Func`1 condition)
at Moq.Mock`1.Setup(Expression`1 expression)
at BrickPile.Tests.Web.Routing.PathResolverTests.Home_Page_With_Default_Action(String path) in PathResolverTests.cs: line 26
Instead of mocking the document session, have you thought about using the embeddabledocumentstore? It could run completely in memory and you have the full database as backend for your tests.
See also this blog post which describes some of the backgrounds: http://novuscraft.com/blog/ravendb-and-the-repository-pattern
This question inspired a blog post.
The short answer: Don't. You're coupling your application to RavenDB and violating the Interface Segregation Principle. Instead, write a custom interface that specifies precisely what services your class (the system under test) needs. Write a wrapper class that implements that and delegates to RavenDB. This might use the Repository Pattern, or it might be something simpler. Your interface should be simple to mock.
You need to mock whatever IDocumentSession.Query() returns as a separate mock so that you can then setup the customize call. I'm typing this on my phone so I can't easily give you an example.