I am finding it difficult to stub methods in structs in swift. I can do it currently using a way that I'll explain below, but it feels wrong to me and would like an opinion on it.
I do not use any third party libraries for stubbing, instead I prefer to override the specific method whose result I need to change. Prior to swift, I would always use classes - so it was easy to subclass and override the method that I needed mocked in my unit test case.
Now most of my constructs are structs as they do not really need to be reference types. But then I cannot override any method in my test cases. I do it currently using protocol extensions as outlined below -
protocol AProtocol {
func a()
func b() // This calls a()
}
extension AProtocol {
func a(){
//Default implementation of a()
}
func b(){
//Default implementation of b() which also calls a()
}
}
struct A:AProtocol {
// Empty. struct A will be used by other classes/structs in the code
}
In my test case
struct TestA:AProtocol {
func a() {
Some mock implementation of a() so that b() can be tested
}
}
So my question is this - There is no real need for struct A to be implemented via a protocol. None of the other classes or structs will ever implement AProtocol. But this is the only way I can mock its methods for unit testing. I think the WWDC session on protocol extensions also showed this way of unit testing, but basically I do not need my struct as an implementation of a protocol.
Is there any other way to stub struct methods in swift (without using any third party libs)? Or a better way to test a struct's methods.
I'm going to be the person that doesn't answer the question and explores whether you really need to do what you ask I'm afraid.
My question is whether you really need mock the struct. For non mutating functions set up the struct and test the return value. For mutating functions check the state afterwards is as you expect.
With structs there shouldn't generally be side effects beyond the modification so there is no need to track exactly what other functions are called.
The bit that may be close enough to an answer to be slightly helpful:
If you really are doing something with side effects outside the struct I would suggest that you make the object that the effects are being done to or on injectable so that with an additional testing only init you can inject an alternate mock object to receive the side effect calls.
Related
I understand that generally I cannot instantiate a protocol.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
My code is as below and line:
protocol Solution {
var answer: String { get }
}
protocol Problem {
var pose: String { get }
}
protocol SolvableProblem: Problem {
func solve() -> Solution?
}
protocol ProblemGenerator {
func next() -> SolvableProblem
}
protocol Puzzle {
var problem: Problem { get }
var solution: Solution { get }
init(problem: Problem, solution: Solution)
}
protocol PuzzleGenerator {
func next() -> Puzzle
}
protocol FindBySolvePuzzleGenerator: PuzzleGenerator {
var problemGenerator: ProblemGenerator { get }
}
extension FindBySolvePuzzleGenerator {
func next() -> Puzzle {
while true {
let problem = problemGenerator.next()
if let solution = problem.solve() {
return Puzzle(problem: problem, solution: solution)
}
}
}
}
The line:
return Puzzle(problem: problem, solution: solution)
gives error: Protocol type 'Puzzle' cannot be instantiated
Imagine protocols are adjectives. Movable says you can move it, Red says it has color = "red"... but they don't say what it is. You need a noun. A Red, Movable Car. You can instantiate a Car, even when low on details. You cannot instantiate a Red.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
Protocols must be adopted by classes, and there might be a dozen different classes that all adopt your Puzzle protocol. The compiler has no idea which of those classes to instantiate.
Protocols give us the power to compose interfaces without the complexity of multiple inheritance. In a multiple inheritance language like C++, you have to deal with the fact that a single class D might inherit from two other classes, B and C, and those two classes might happen to have methods or instance variables with the same name. If they both have a methodA(), and B::methodA() and C::methodA() are different, which one do you use when someone call's D's inherited methodA()? Worse, what if B and C are both derived from a common base class A? Protocols avoid a lot of that by not being directly instantiable, while still providing the interface polymorphism that makes multiple inheritance attractive.
I understand that I can't do it - I just want to understand why the
compiler can't do it?
Because protocols in Swift represent abstraction mechanism. When it comes to abstraction, you could think about it as a template, we don't have to care about the details of how it behaves or what's its properties; Thus it makes no sense to be able to create an object from it.
As a real world example, consider that I just said "Table" (as an abstracted level), I would be pretty sure that you would understand what I am talking about! nevertheless we are not mentioning details about it (such as its material or how many legs it has...); At some point if I said "create a table for me" (instantiate an object) you have the ask me about specs! and that's why the complier won't let you create object directly from a protocol. That's the point of making things to be abstracted.
Also, checking: Why can't an object of abstract class be created? might be helpful.
Unfortunately swift does not allow that even with such "hack"
You would need to use a class that confirms to that protocol as an object you refer to.
When you instantiate an object, the Operating System has to know how to allocate and deal with that kind of object in the memory: Is it a reference type (Classes)? Strong, weak or unowned reference? Or is it a value type (Structs, Strings, Int, etc)?
Reference types are stored in the Heap, while value types live in the Stack. Here is a thorough explanation of the difference between the two.
Only Reference and Value types (objects) can be instantiated. So, only the objects that conform to that protocol can then be instantiated, not the protocol itself. A protocol is not an object, it is a general description or schema of a certain behavior of objects.
As to Initialization, here what the Apple docs say:
Initialization is the process of preparing an instance of a class,
structure, or enumeration for use. This process involves setting an
initial value for each stored property on that instance and performing
any other setup or initialization that is required before the new
instance is ready for use.
I'm faced with a situation where I am defining a reusable base class in a module, and I want to provide certain functions that should be callable only by subclasses, not external users of that subclass.
I'm writing a framework and packaging it as a Swift module. Part of my framework includes a base class that can be subclassed to add functionality, but whereby the derived class also has a further external purpose as well. Imagine defining a new kind of view: it derives from UIView or NSView, then provides additional logic, and is then itself instantiated by another party.
In this case, I'm the one defining the UIView-like class that is intended to be subclassed, and along with it comes a lot of private UIView internal stuff, like measurement, arranging, who knows, internal stuff.
The point is, end users of this new view class don't want to see the internals of the architecture that supported the subclassing, those should be completely inside the black box of what the subclass represents.
And it strikes me that this is now impossible in Swift.
I really don't understand why Swift got rid of protected access control. According to Apple, the function that I want to expose only to subclasses "isn't really useful outside the subclass, so protection isn’t critical".
Am I missing something? Is this a whole class of design patterns that Swift simply cannot support?
One thought that occurs to me is I could perhaps split up the public-public and the private-public parts of my class into two parts, perhaps using protocols, whereby public-public users would only see the public protocol and "private" public users would see the "private" protocol as well. Alas this seems like a lot of engineering for something that used to be free.
FWIW — I've been continually asking for better access control in Swift (including protected) since before there was access control in Swift. Now, 3.5 years after we were told to give the Swift approach to access control a try, Swift has been my primary language for almost 3 of those years and I still think the access control paradigm is clumsy and unable to model concepts that are easy in almost all similar languages.
The largest mitigating factor for me is that Swift has steered me away from ever using inheritance and subclassing 95% of the time, which I think is a good thing. So this issue comes up less than it may have otherwise. But for situations exactly as you are describing, there isn't an equivalent way to accomplish what you are doing using only protocols and protocol extensions, so you are stuck either polluting a public API with possibly harmful internal details, or using some workaround (like the one that follows) which has the smallest possible public API exposure, and simulates what you want at the cost of boilerplate and awkwardness.
That said, the approach I take is somewhat inspired by Objective C, where there is also no real protected access control, but the convention is to declare a public API header (which client code will import and reference) and a special "+Subclassing" header which only subclasses will import in their implementation, giving them visibility into the not-for-public-consumption internals.
In Swift, this isn't directly possible either, but given a class like this:
open class SomeClass {
private var foo: String
private var bar: Data
public init(){
foo = "foo"
bar = Data()
}
private func doInternalThing() {
print(foo)
}
}
You can add a nested "Protected" wrapper via extension (has to be in the same file as your class declaration), which takes an instance of the class (or a subclass) and exposes the protected-level internals as a sort of proxy:
// Create a nested "Protected" type, which can accept an instance of SomeClass (or one of its subclasses) and expose the internal / protected members on it
public extension SomeClass {
public class Protected {
unowned private var someClass: SomeClass
public var foo: String {
get {
return someClass.foo
}
set {
someClass.foo = newValue
}
}
public init(_ someClass: SomeClass) {
self.someClass = someClass
}
public func doInternalThing() {
someClass.doInternalThing()
}
}
}
Outside of the framework, in the client application, the protected members are accessed in a subclass like this:
class SomeSubclass: SomeClass {
private lazy var protected: SomeClass.Protected = { SomeClass.Protected(self) }()
func doSomething() {
protected.foo = "newFoo" // Accesses the protected property foo and sets a new value "newFoo"
protected.doInternalThing() // Prints "newFoo" by calling the protected method doInternalThing which prints the foo property.
}
}
There are pros and cons for this approach. The cons are mainly the amount of boilerplate you need to write to map all your properties and functions from the Protected wrapper to the actual class instance as shown above. Also, there is no avoiding the fact that consumers will see SomeClass.Protected as a publicly visible type, but hopefully it's clear that it shouldn't be used and it's difficult enough to use it arbitrarily that it won't happen.
The pros are that there isn't a lot of boilerplate or pain for clients when creating subclasses, and its easy to declare a lazy "protected" var to get the desired API. It's pretty unlikely that non-subclass would stumble upon or use this API accidentally or unwittingly, and it's mostly hidden as desired. Instances of SomeSubclass will not show any extra protected API in code completion or to outside code at all.
I encourage anyone else who thinks access control — or really in this case, API visibility and organization — to be easier than it is in Swift today to let the Swift team know via the Swift forums, Twitter, or bugs.swift.org.
You can kinda, sorta work around it by separating out the for-subclasses stuff into a separate protocol, like this:
class Widget {
protocol SubclassStuff {
func foo()
func bar()
func baz()
}
func makeSubclassStuff() -> SubclassStuff {
// provide some kind of defaults, or throw a fatalError if this is
// an abstract superclass
}
private lazy var subclassStuff: SubclassStuff = {
return self.makeSubclassStuff()
}()
}
Then you can at least group the stuff that's not to be called in one place, to avoid it polluting the public interface any more than absolutely necessary and getting called by accident.
You can also reconsider whether you really need the subclass pattern here, and consider using a protocol instead. Unfortunately, since protocols can't nest types yet, this involves giving the subclass-specific protocol an Objective-C-style prefixed name:
protocol WidgetConcreteTypeStuff {
...
}
protocol Widget {
var concreteTypeStuff: WidgetConcreteTypeStuff { get }
}
I have few questions for Swift developers regarding the concept of abstract classes.
How do you define an abstract class in Swift? Is there any way to prevent a class from being instantiated, while providing an initializer for its subclasses to use?
How do you define abstract methods, while implementing others? When defining abstract methods, Apple generally points you to protocols (interfaces). But they only solve the first part of my question, since all of the methods they define are abstract. What do you do when you want to have both abstract and non-abstract methods in your class?
What about generics? You might have thought about using protocols together with extensions (categories). But then there is an issue with generics because protocols can't have generic types, only typealiases.
I have done my homework and I know about solving these issues using methods, such as fatalError() or preconditionFailure() in the superclass and then overriding them in a base class. But that seems like ugly object design to me.
The reason I'm posting this is to find out whether there exists more general and universal solution.
Thanks in advance,
Petr.
As of today (April 7, 2016), the proposal to introduce abstract classes and methods to Swift (SE-0026) has been deferred.
Joe Groff posted the following in swift-evolution-announce on March 7, 2016:
The proposal has been deferred from Swift 3. Discussion centered around whether abstract classes fit in the direction of Swift as a "protocol-oriented" language. Beyond any religious dogmas, Swift intends to be a pragmatic language that lets users get work done. The fact of the matter today is that one of Swift's primary target platforms is the inheritance-heavy Cocoa framework, and that Swift 2's protocols fall short of abstract classes in several respects [...].
We'd like to revisit this feature once the core goals of Swift 3 have been addressed, so we can more accurately consider its value in the context of a more complete generics implementation, and so we can address the finer points of its design.
I encourage you to read the full email, but I think the conclusion is the same as what you came up with in your question: we're currently stuck with the Objective-C way of doing things (raising exceptions).
There is no Abstract concept in Swift. But we can achieve that scenario by using Inheritance concept like the code below:
class ParentVC:UIViewController {
func loadInformation() {
}
}
class ChildVC:ParentVC {
// This is an Abstract Method
override func loadInformation() {
}
}
How do you define abstract methods, while implementing others?
The "swifty" way of achieving this is combining protocols and extensions, sometimes also typealiases. For data, you are going to define abstract properties in your protocol, then re-define them in a concrete class, then unite all that using a typealias and the & operator:
protocol BaseAbstract: class {
var data: String { get set }
func abstractMethod()
func concreteMethod()
}
extension BaseAbstract {
// Define your concrete methods that use the abstract part of the protocol, e.g.:
func concreteMethod() {
if !data.isEmpty {
abstractMethod()
}
}
}
class BaseImpl {
// This is required since we can't define properties in extensions.
// Therefore, we define a class with a concrete property and then
// unite it with the protocol above in the typealias below.
var data: String = "Hello, concrete!"
}
typealias Base = BaseAbstract & BaseImpl // et voila, `Base` is now ready to be subclassed
class Subclass: Base {
func abstractMethod() { // enforced by the compiler
}
}
(It can get tricker if you have generics in this scenario. Currently trying to figure it out.)
swift code is below:
func swizzleMethod()
{
let method:Method = class_getInstanceMethod(object_getClass(self), Selector("function1"))
self.function1()
let swizzledMethod:Method = class_getInstanceMethod(object_getClass(self), Selector("function2"))
method_exchangeImplementations(method, swizzledMethod)
self.function1()
}
func function1()
{
print("function1 log")
}
func function2()
{
print("function2 log")
}
it logs:
function1 log
function1 log
/////
my environment is swift based project, xcode7.2
This always run into the funtion1 method body, so I think it exchanged failed, this two method is in the same class, anyone know why?
I get the answer, add "dynamic" keyword in front of method name!!!
like this:
dynamic func function1()
{
print("function1 log")
}
dynamic func function2()
{
print("function2 log")
}
Reason:
Swift optimizes code to call direct memory addresses instead of looking up the method location at runtime as in Objective-C. so we need tell the code run treat it as Objective-C code.
Answer Detail:
Method swizzling is a technique that substitutes one method implementation for another. If you're not familiar with swizzling, check out this blog post. Swift optimizes code to call direct memory addresses instead of looking up the method location at runtime as in Objective-C. So by default swizzling doesn’t work in Swift classes unless we:
1. Disable this optimization with the dynamic keyword. This is the preferred choice, and the choice that makes the most sense if the codebase is entirely in Swift.
2. Extend NSObject. Never do this only for method swizzling (use dynamic instead). It’s useful to know that method swizzling will work in already existing classes that have NSObject as their base class, but we're better off selectively choosing methods with dynamic .
3. Use the #objc annotation on the method being swizzled. This is appropriate if the method we would like to swizzle also needs to be exposed to Objective-C code at the same time.
thanks to the article: 15 Tips to Become a Better Swift Developer
updated Clarifying question to make clear this is an issue with a protocol that has a typealias, causing the general error of can only be used as a generic constraint.
I have the following class/protocol pattern:
protocol Storage { /* ... */ }
protocol StorageView {
typealias StorageType: Storage
/* ... */
}
class StorageColumnView<StorageType:Storage>: StorageView { /* ... */ }
class SomeStorage: Storage { /* ... */ }
and I want to define a class that combines my Storage class with View class. Ideally, it would look something like:
class MyClass<S:StorageType> {
var view:ViewType<S>
}
This won't compile because you can't specify a variable's type based on a protocol. After searching around, the general answer I found was to use type-erasure and make a AnyView class. However, such an approach seems cumbersome for a single variable (in theory this is the only place I'll use it) and difficult because StorageView has enough functionality to make wrapping each variable time consuming. Additionally, the methods of the view may get called a decent amount (yes, premature optimization is the root of all evil, but its subscripts will be called in loops), so I'm worried about the overhead.
Three alternative methods I'm currently investigating are:
(1) Declaring view as AnyObject, and then casting it to the correct type:
var view:AnyObject
// ...
view = StorageColumnView(/*...*/)
// ...
if let v = view as? StorageView {
// operate on v
}
(2) Treating view as a function, and letting the type be defined using a closure:
var view: () -> StorageView
// ...
view = { return StorageColumnView(self) }
/// ...
view().doX()
(3) Parameterizing MyClass by the ViewType rather than Storage:
class MyClass<V:ViewType> {
typealias StorageType = ViewType.StorageType
}
I'm trying to evaluate which of the 3 options is best (in terms of Swift style as well as speed), or if there is another alternative I'm not aware of (or I really should just use type-erasure to solve this problem -- though it seems like AnyObject is essentially just that).
So:
Are there any major penalties for the first approach? Is this closer to c++'s static_cast or dynamic_cast?
Is there a way to make the closure approach a little more user-friendly (i.e. I rather not require the user to actually pass in a closure, but rather the type). Maybe create a helper function that is a generic that then returns the type?
While the last solution is potentially the cleanest in amount of extra code required, it also requires a design that is against what I'm trying to do. The ViewType is really supposed to act like a delegate, and be fungible. Instead, I'm not creating a specific type of MyClass based on the ViewType.
Any and all opinions welcome on the best design pattern! I'm a little surprised that making a delegate-type pattern is so difficult (assuming I'm doing things correctly), considering that is primarily how Objective-C is used in Cocoa.
Also, does anyone know the rationale for not letting a variable to be defined as a protocol type that has a typealias? What's the underlying difference between a protocol with and without a Self?