diff --git a/.gitignore b/.gitignore
index ec0d7020029c6ff3dff5f48f26b5884c79fcf72a..ddae209f43c4546704866301774c0ed68c6a4f64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,6 @@
 docs/build
 test/data/ecoli_core.xml
 /vscode
-/.vscode
\ No newline at end of file
+/.vscode
+*.jl.*.cov
+.*.swp
diff --git a/src/base/solver.jl b/src/base/solver.jl
index 0e60d659e4cbdaeb9d0be8536a0d1d26101d90e6..fca335d40649659a24191fc72eb1eb22cb90aed1 100644
--- a/src/base/solver.jl
+++ b/src/base/solver.jl
@@ -30,7 +30,11 @@ end
 Use JuMP to optimize an instance of a [`MetabolicModel`](@ref). Returns a tuple
 that contains the new model and a vector of its variables.
 """
-function optimizeModel(model::LM, optimizer; sense = MOI.MIN_SENSE) where {LM<:MetabolicModel}
+function optimizeModel(
+    model::LM,
+    optimizer;
+    sense = MOI.MIN_SENSE,
+) where {LM<:MetabolicModel}
     optimization_model, x = makeOptimizationModel(model, optimizer; sense = sense)
     JuMP.optimize!(optimization_model)
     return (optimization_model, x)
diff --git a/src/base/utilities.jl b/src/base/utilities.jl
index b5b5487cd585cee78677504612ea62c92c1c46c6..59f202da7e1c259e25bac84fdb206e92d8e3b528 100644
--- a/src/base/utilities.jl
+++ b/src/base/utilities.jl
@@ -1,27 +1,20 @@
-function Base.isequal(model1::LinearModel, model2::LinearModel)
-    return model1.S == model2.S &&
-           model1.b == model2.b &&
-           model1.C == model2.C &&
-           model1.cl == model2.cl &&
-           model1.cu == model2.cu &&
-           model1.c == model2.c &&
-           model1.xl == model2.xl &&
-           model1.xu == model2.xu &&
-           model1.rxns == model2.rxns &&
-           model1.mets == model2.mets
-end
+Base.isequal(model1::LinearModel, model2::LinearModel) =
+    isequal(model1.S, model2.S) &&
+    isequal(model1.b, model2.b) &&
+    isequal(model1.c, model2.c) &&
+    isequal(model1.xl, model2.xl) &&
+    isequal(model1.xu, model2.xu) &&
+    isequal(model1.rxns, model2.rxns) &&
+    isequal(model1.mets, model2.mets)
 
-function Base.copy(model::LinearModel)
-    return LinearModel(
-        model.S,
-        model.b,
-        model.C,
-        model.cl,
-        model.cu,
-        model.c,
-        model.xl,
-        model.xu,
-        model.rxns,
-        model.mets,
-    )
-end
+Base.copy(model::LinearModel) =
+    LinearModel(model.S, model.b, model.c, model.xl, model.xu, model.rxns, model.mets)
+
+Base.isequal(model1::CoupledLinearModel, model2::CoupledLinearModel) =
+    isequal(model1.lm, model2.lm) &&
+    isequal(model1.C, model2.C) &&
+    isequal(model1.cl, model2.cl) &&
+    isequal(model1.cu, model2.cu)
+
+Base.copy(model::CoupledLinearModel) =
+    CoupledLinearModel(model.lm, model.C, model.cl, model.cu)
diff --git a/src/io/sbml.jl b/src/io/sbml.jl
index d150ed2eaadca1806ed340e9e64d60957129fa66..3031492d7888952abc7674dbc8a1a9076d64d1d0 100644
--- a/src/io/sbml.jl
+++ b/src/io/sbml.jl
@@ -2,35 +2,4 @@
 """
 Import a LinearModel from a SBML file
 """
-function loadSBMLModel(filename::String)::LinearModel
-    model = SBML.readSBML(filename)
-
-    mets, rxns, S = SBML.getS(model)
-    b = zeros(length(mets))
-    c = SBML.getOCs(model)
-
-    lbu = SBML.getLBs(model)
-    ubu = SBML.getUBs(model)
-
-    # SBML has units that we can't easily interpret yet, BUT the chances are
-    # that in a reasonable SBML file all units will be the same and we don't
-    # need to care about them at all. So we just check it here and throw an
-    # error if not.
-
-    unit = lbu[1][2]
-    getvalue = (val, _)::Tuple -> val
-    getunit = (_, unit)::Tuple -> unit
-
-    allunits = unique([getunit.(lbu) getunit.(ubu)])
-
-    if length(allunits) != 1
-        throw(
-            DomainError(
-                allunits,
-                "The SBML file uses multiple units; loading needs conversion",
-            ),
-        )
-    end
-
-    return LinearModel(S, b, c, getvalue.(lbu), getvalue.(ubu), rxns, mets)
-end
+loadSBMLModel(filename::String)::SBMLModel = SBMLModel(SBML.readSBML(filename))
diff --git a/src/reconstruction/coupling.jl b/src/reconstruction/coupling.jl
index ecce84d4b1b0a1f734fc6db480127a595f3cc483..9e8e0f61fc7d8a319d82d4031872ddf6b5510b60 100644
--- a/src/reconstruction/coupling.jl
+++ b/src/reconstruction/coupling.jl
@@ -1,31 +1,20 @@
 """
-Verifies that vectors and matrices have the expected dimensions.
-"""
-function checkCouplingConstraintsInputDimensions(
-    m::LinearModel,
-    C::M,
-    cl::V,
-    cu::V,
-) where {M<:MatType,V<:VecType}
-
-    length(cu) == length(cl) ||
-        throw(DimensionMismatch("`cl` and `cu` don't have the same size"))
-    size(C) == (length(cl), nReactions(m)) || throw(
-        DimensionMismatch("`C` size should be length(cl) x the number of reactions in m"),
-    )
-end
-
-"""
-Add constraints of the following form to a LinearModel and return a modified one.
+Add constraints of the following form to a CoupledLinearModel and return a modified one.
 
 The arguments are same as for in-place `addCouplingConstraints!`.
 """
-function addCouplingConstraints(m::LinearModel, args...)
+function addCouplingConstraints(m::CoupledLinearModel, args...)
     newLp = deepcopy(m)
     addCouplingConstraints!(newLp, args...)
     return newLp
 end
 
+"""
+Add constraints to a plain `LinearModel` (converts it to the coupled type)
+"""
+addCouplingConstraints(m::LinearModel, args...) =
+    addCouplingConstraints(convert(CoupledLinearModel, m), args...)
+
 """
 In-place add coupling constraints in form
 ```
@@ -33,7 +22,7 @@ In-place add coupling constraints in form
 ```
 """
 function addCouplingConstraints!(
-    m::LinearModel,
+    m::CoupledLinearModel,
     c::V,
     cl::AbstractFloat,
     cu::AbstractFloat,
@@ -48,21 +37,20 @@ end
 
 
 function addCouplingConstraints!(
-    m::LinearModel,
+    m::CoupledLinearModel,
     C::M,
     cl::V,
     cu::V,
 ) where {M<:MatType,V<:VecType}
 
-    C = sparse(C)
-    cl = sparse(cl)
-    cu = sparse(cu)
-
-    checkCouplingConstraintsInputDimensions(m, C, cl, cu)
+    all([length(cu), length(cl)] .== size(C, 1)) ||
+        throw(DimensionMismatch("mismatched numbers of constraints"))
+    size(C, 2) == nReactions(m) ||
+        throw(DimensionMismatch("mismatched number of reactions"))
 
-    m.C = vcat(m.C, C)
-    m.cl = vcat(m.cl, cl)
-    m.cu = vcat(m.cu, cu)
+    m.C = vcat(m.C, sparse(C))
+    m.cl = vcat(m.cl, sparse(cl))
+    m.cu = vcat(m.cu, sparse(cu))
 end
 
 
@@ -71,7 +59,7 @@ Remove coupling constraints from the linear model and return the modified model.
 
 Arguments are the same as for in-place version `removeCouplingConstraints!`.
 """
-function removeCouplingConstraints(m::LinearModel, args...)
+function removeCouplingConstraints(m::CoupledLinearModel, args...)
     newModel = deepcopy(m)
     removeCouplingConstraints!(newModel, args...)
     return newModel
@@ -79,14 +67,14 @@ end
 
 
 """
-Removes a set of coupling constraints from a LinearModel in-place.
+Removes a set of coupling constraints from a CoupledLinearModel in-place.
 """
-function removeCouplingConstraints!(m::LinearModel, constraint::Int)
+function removeCouplingConstraints!(m::CoupledLinearModel, constraint::Int)
     removeCouplingConstraints!(m, [constraint])
 end
 
 
-function removeCouplingConstraints!(m::LinearModel, constraints::Vector{Int})
+function removeCouplingConstraints!(m::CoupledLinearModel, constraints::Vector{Int})
     toBeKept = filter(e -> e ∉ constraints, 1:nCouplingConstraints(m))
     m.C = m.C[toBeKept, :]
     m.cl = m.cl[toBeKept]
@@ -98,7 +86,7 @@ end
 Change the lower and/or upper bounds ('cl' and 'cu') for given coupling constraints
 """
 function changeCouplingBounds!(
-    model::LinearModel,
+    model::CoupledLinearModel,
     constraints::Vector{Int};
     cl::V = Array{Float64}(undef, 0),
     cu::V = Array{Float64}(undef, 0),
diff --git a/src/reconstruction/modeling.jl b/src/reconstruction/modeling.jl
index d284eb4ac9f7effcf69d56e4ede847ac11efabaa..d19a17070aa2827eb2e5d26cf86a5b9d436f8ad5 100644
--- a/src/reconstruction/modeling.jl
+++ b/src/reconstruction/modeling.jl
@@ -104,12 +104,14 @@ function addReactions(
     xl = sparse(xl)
     xu = sparse(xu)
 
-    checkInputDimensions(Sp, b, c, xl, xu, rxns, mets)
+    all([length(b), length(mets)] .== size(Sp, 1)) ||
+        throw(DimensionMismatch("inconsistent number of metabolites"))
+    all(length.([c, xl, xu, rxns]) .== size(Sp, 2)) ||
+        throw(DimensionMismatch("inconsistent number of reactions"))
 
     newReactions = findall(Bool[!(rxn in m.rxns) for rxn in rxns])
     newMetabolites = findall(Bool[!(met in m.mets) for met in mets])
 
-
     if checkConsistency
         (newReactions1, newMetabolites1) =
             verifyConsistency(m, Sp, b, c, xl, xu, rxns, mets, newReactions, newMetabolites)
@@ -130,12 +132,13 @@ function addReactions(
 
     newS = hcat(extS, extSp)
     newb = vcat(m.b, b[newMetabolites])
-    newC = hcat(m.C, spzeros(size(m.C, 1), length(newReactions)))
+    #newC = hcat(m.C, spzeros(size(m.C, 1), length(newReactions)))
     newc = vcat(m.c, c[newReactions])
     newxl = vcat(m.xl, xl[newReactions])
     newxu = vcat(m.xu, xu[newReactions])
     newRxns = vcat(m.rxns, rxns[newReactions])
-    newLp = LinearModel(newS, newb, newC, m.cl, m.cu, newc, newxl, newxu, newRxns, newMets)
+    #newLp = LinearModel(newS, newb, newC, m.cl, m.cu, newc, newxl, newxu, newRxns, newMets)
+    newLp = LinearModel(newS, newb, newc, newxl, newxu, newRxns, newMets)
 
     if checkConsistency
         return (newLp, newReactions, newMetabolites)
@@ -144,56 +147,6 @@ function addReactions(
     end
 end
 
-"""
-Verifies that vectors and matrices have the expected dimensions.
-"""
-function checkInputDimensions(
-    S::M1,
-    b::V,
-    C::M2,
-    cl::V,
-    cu::V,
-    c::V,
-    xl::V,
-    xu::V,
-    rxns::K,
-    mets::K,
-) where {M1<:MatType,M2<:MatType,V<:VecType,K<:StringVecType}
-    n_c = length(c)
-
-    length(cu) == length(cl) ||
-        throw(DimensionMismatch("`cl` and `cu` don't have the same size"))
-    size(C) == (length(cu), n_c) ||
-        throw(DimensionMismatch("`C` shape doesn't match with `cu` and `c`"))
-
-    checkInputDimensions(S, b, c, xl, xu, rxns, mets)
-
-end
-
-function checkInputDimensions(
-    S::M,
-    b::V,
-    c::V,
-    xl::V,
-    xu::V,
-    rxns::K,
-    mets::K,
-) where {M<:MatType,V<:VecType,K<:StringVecType}
-
-    n_c = length(c)
-    n_b = length(b)
-
-    length(xu) == length(xl) ||
-        throw(DimensionMismatch("`xl` and `xu` don't have the same size"))
-    n_c == length(xl) || throw(DimensionMismatch("`c` doesn't have the same size as `xl`"))
-
-    size(S) == (n_b, n_c) ||
-        throw(DimensionMismatch("`S` shape doesn't match with `c` and `mets`"))
-
-    length(rxns) == n_c || throw(DimensionMismatch("`rxns` size doesn't match with `S`"))
-    length(mets) == n_b || throw(DimensionMismatch("`mets` size doesn't match with `S`"))
-end
-
 """
 Verifies the consistency of a given model
 """
@@ -250,14 +203,15 @@ function removeReactions(m::LinearModel, rxns::Vector{Int})
     unique!(metsToKeep)
     newS = m.S[metsToKeep, rxnsToKeep]
     newb = m.b[metsToKeep]
-    newC = m.C[:, rxnsToKeep]
+    #newC = m.C[:, rxnsToKeep]
     newc = m.c[rxnsToKeep]
     newxl = m.xl[rxnsToKeep]
     newxu = m.xu[rxnsToKeep]
     newRxns = m.rxns[rxnsToKeep]
     newMets = m.mets[metsToKeep]
     newModel =
-        LinearModel(newS, newb, newC, m.cl, m.cu, newc, newxl, newxu, newRxns, newMets)
+    #LinearModel(newS, newb, newC, m.cl, m.cu, newc, newxl, newxu, newRxns, newMets)
+        LinearModel(newS, newb, newc, newxl, newxu, newRxns, newMets)
     return newModel
 end
 
@@ -271,7 +225,7 @@ function removeReactions(m::LinearModel, rxn::String)
 end
 
 
-function removeReactions(m::LinearModel, rxns::Array{String,1})
+function removeReactions(m::LinearModel, rxns::Vector{String})
     rxnIndices = [findfirst(isequal(name), m.rxns) for name in intersect(rxns, m.rxns)]
     if isempty(rxnIndices)
         return m
diff --git a/src/types/linearModel.jl b/src/types/linearModel.jl
index 5e83695b9667b9eb0a12f66180d37ca27bb389a3..74ecd6110002c0d67f40dc074a58c7a6a64949cc 100644
--- a/src/types/linearModel.jl
+++ b/src/types/linearModel.jl
@@ -6,16 +6,12 @@ A concrete linear optimization problem of the form:
 ```
 min c^T x
 s.t. S x = b
-    cₗ ≤ C x ≤ cᵤ
-    xₗ ≤ x ≤ xᵤ
+      xₗ ≤ x ≤ xᵤ
 ```
 """
 mutable struct LinearModel <: MetabolicModel
     S::SparseMat
     b::SparseVec
-    C::SparseMat
-    cl::SparseVec
-    cu::SparseVec
     c::SparseVec
     xl::SparseVec
     xu::SparseVec
@@ -32,43 +28,13 @@ mutable struct LinearModel <: MetabolicModel
         mets::K,
     ) where {V<:VecType,M<:MatType,K<:StringVecType}
 
-        sS = sparse(S)
-        sb = sparse(b)
-        sC = spzeros(0, length(c))
-        scl = spzeros(0)
-        scu = spzeros(0)
-        sc = sparse(c)
-        sxl = sparse(xl)
-        sxu = sparse(xu)
+        all([length(b), length(mets)] .== size(S, 1)) ||
+            throw(DimensionMismatch("inconsistent number of reactions"))
 
-        LinearModel(sS, sb, sC, scl, scu, sc, sxl, sxu, rxns, mets)
-    end
-
-    function LinearModel(
-        S::M1,
-        b::V,
-        C::M2,
-        cl::V,
-        cu::V,
-        c::V,
-        xl::V,
-        xu::V,
-        rxns::K,
-        mets::K,
-    ) where {V<:VecType,M1<:MatType,M2<:MatType,K<:StringVecType}
+        all([length(c), length(xl), length(xu), length(rxns)] .== size(S, 2)) ||
+            throw(DimensionMismatch("inconsistent number of reactions"))
 
-        checkInputDimensions(S, b, C, cl, cu, c, xl, xu, rxns, mets)
-
-        sS = sparse(S)
-        sb = sparse(b)
-        sC = sparse(C)
-        scl = sparse(cl)
-        scu = sparse(cu)
-        sc = sparse(c)
-        sxl = sparse(xl)
-        sxu = sparse(xu)
-
-        new(sS, sb, sC, scl, scu, sc, sxl, sxu, rxns, mets)
+        new(sparse(S), sparse(b), sparse(c), sparse(xl), sparse(xu), rxns, mets)
     end
 end
 
@@ -129,17 +95,36 @@ end
 """
     coupling(a::LinearModel)::SparseMat
 
-Coupling constraint matrix for a `LinearModel`.
+Coupling constraint matrix for a `LinearModel`, actually empty.
 """
 function coupling(a::LinearModel)::SparseMat
-    a.C
+    spzeros(0, nReactions(a))
 end
 
 """
     couplingBounds(a::LinearModel)::Tuple{SparseVec,SparseVec}
 
-Coupling bounds for a `LinearModel`.
+Coupling bounds for a `LinearModel`, in fact always empty.
 """
 function couplingBounds(a::LinearModel)::Tuple{SparseVec,SparseVec}
-    (a.cl, a.cu)
+    (spzeros(0), spzeros(0))
+end
+
+
+"""
+    Base.convert(::Type{LinearModel}, m::M) where {M <: MetabolicModel}
+
+Make a `LinearModel` out of any compatible model type.
+"""
+function Base.convert(::Type{LinearModel}, m::M) where {M<:MetabolicModel}
+    (xl, xu) = bounds(m)
+    LinearModel(
+        stoichiometry(m),
+        balance(m),
+        objective(m),
+        xl,
+        xu,
+        reactions(m),
+        metabolites(m),
+    )
 end
diff --git a/src/types/linearModelCoupled.jl b/src/types/linearModelCoupled.jl
new file mode 100644
index 0000000000000000000000000000000000000000..a7f3c2a7cb911a4abce830ee2da828e5bc35f125
--- /dev/null
+++ b/src/types/linearModelCoupled.jl
@@ -0,0 +1,74 @@
+
+"""
+    struct CoupledLinearModel <: MetabolicModel
+
+The linear model with additional coupling constraints in the form
+```
+    cₗ ≤ C x ≤ cᵤ
+```
+"""
+mutable struct CoupledLinearModel <: MetabolicModel
+    lm::LinearModel
+    C::SparseMat
+    cl::SparseVec
+    cu::SparseVec
+
+    function CoupledLinearModel(
+        lm::MetabolicModel,
+        C::M,
+        cl::V,
+        cu::V,
+    ) where {V<:VecType,M<:MatType}
+
+        length(cu) == length(cl) ||
+            throw(DimensionMismatch("`cl` and `cu` need to have the same size"))
+        size(C) == (length(cu), nReactions(lm)) ||
+            throw(DimensionMismatch("wrong dimensions of `C`"))
+
+        new(convert(LinearModel, lm), sparse(C), sparse(cl), sparse(cu))
+    end
+end
+
+reactions(a::CoupledLinearModel) = reactions(a.lm)
+metabolites(a::CoupledLinearModel) = metabolites(a.lm)
+stoichiometry(a::CoupledLinearModel) = stoichiometry(a.lm)
+bounds(a::CoupledLinearModel) = bounds(a.lm)
+balance(a::CoupledLinearModel) = balance(a.lm)
+objective(a::CoupledLinearModel) = objective(a.lm)
+
+"""
+    coupling(a::CoupledLinearModel)::SparseMat
+
+Coupling constraint matrix for a `CoupledLinearModel`.
+"""
+function coupling(a::CoupledLinearModel)::SparseMat
+    a.C
+end
+
+"""
+    nCouplingConstraints(a::CoupledLinearModel)::Int
+
+The number of coupling constraints in a `CoupledLinearModel`.
+"""
+function nCouplingConstraints(a::CoupledLinearModel)::Int
+    return size(a.C, 1)
+end
+
+"""
+    couplingBounds(a::CoupledLinearModel)::Tuple{SparseVec,SparseVec}
+
+Coupling bounds for a `CoupledLinearModel`.
+"""
+function couplingBounds(a::CoupledLinearModel)::Tuple{SparseVec,SparseVec}
+    (a.cl, a.cu)
+end
+
+"""
+    Base.convert(::Type{CoupledLinearModel}, m::M) where {M <: MetabolicModel}
+
+Make a `CoupledLinearModel` out of any compatible model type.
+"""
+function Base.convert(::Type{CoupledLinearModel}, m::M) where {M<:MetabolicModel}
+    (cl, cu) = couplingBounds(m)
+    CoupledLinearModel(convert(LinearModel, m), coupling(m), cl, cu)
+end
diff --git a/src/types/sbmlModel.jl b/src/types/sbmlModel.jl
new file mode 100644
index 0000000000000000000000000000000000000000..79867000a320bdbaf292d2fd66f93331c978fef9
--- /dev/null
+++ b/src/types/sbmlModel.jl
@@ -0,0 +1,55 @@
+"""
+    struct SBMLModel
+
+Thin wrapper around the model from SBML.jl library. Allows easy conversion from
+SBML to any other model format.
+"""
+struct SBMLModel <: MetabolicModel
+    m::SBML.Model
+end
+
+reactions(a::SBMLModel)::Vector{String} = [k for k in keys(a.m.reactions)]
+metabolites(a::SBMLModel)::Vector{String} = [k for k in keys(a.m.species)]
+nReactions(a::SBMLModel)::Int = length(a.m.reactions)
+nMetabolites(a::SBMLModel)::Int = length(a.m.species)
+
+"""
+    stoichiometry(a::SBMLModel)::SparseMat
+
+Recreate the stoichiometry matrix from the SBML model.
+"""
+function stoichiometry(a::SBMLModel)::SparseMat
+    _, _, S = SBML.getS(a.m)
+    return S
+end
+
+"""
+    bounds(a::SBMLModel)::Tuple{SparseVec,SparseVec}
+
+Get the lower and upper flux bounds of a `SBMLModel`. Throws `DomainError` in
+case if the SBML contains mismatching units.
+"""
+function bounds(a::SBMLModel)::Tuple{SparseVec,SparseVec}
+    lbu = SBML.getLBs(a.m)
+    ubu = SBML.getUBs(a.m)
+
+    unit = lbu[1][2]
+    getvalue = (val, _)::Tuple -> val
+    getunit = (_, unit)::Tuple -> unit
+
+    allunits = unique([getunit.(lbu) getunit.(ubu)])
+    length(allunits) == 1 || throw(
+        DomainError(
+            allunits,
+            "The SBML file uses multiple units; loading needs conversion",
+        ),
+    )
+
+    return sparse.((getvalue.(lbu), getvalue.(ubu)))
+end
+
+balance(a::SBMLModel)::SparseVec = spzeros(nMetabolites(a))
+objective(a::SBMLModel)::SparseVec = SBML.getOCs(a.m)
+coupling(a::SBMLModel)::SparseMat = spzeros(0, nReactions(a))
+nCouplingConstraints(a::SBMLModel)::Int = 0
+couplingBounds(a::SBMLModel)::Tuple{SparseVec,SparseVec} = (spzeros(0), spzeros(0))
diff --git a/test/base/utilities.jl b/test/base/utilities.jl
index d317dbba5d8aeb87f7a406b64a829f2b81f5b38b..2f735d5a2ab025a340eaddcf26c2e059aa416290 100644
--- a/test/base/utilities.jl
+++ b/test/base/utilities.jl
@@ -12,4 +12,5 @@
 
     cp = test_coupledLP()
     @test nCouplingConstraints(cp) == 2000
+    @test isequal(cp, copy(cp))
 end
diff --git a/test/data/testModels.jl b/test/data/testModels.jl
index 6fc035805e7f8dd60155ffd0297661c2220f769e..de9809c08dafa64bbcf9de743df0799c1d486b62 100644
--- a/test/data/testModels.jl
+++ b/test/data/testModels.jl
@@ -41,15 +41,17 @@ test_sparseLP() = LinearModel(
     ["m$x" for x = 1:4000],
 )
 
-test_coupledLP() = LinearModel(
-    sprand(4000, 3000, 0.5),
-    sprand(4000, 0.5),
+test_coupledLP() = CoupledLinearModel(
+    LinearModel(
+        sprand(4000, 3000, 0.5),
+        sprand(4000, 0.5),
+        sprand(3000, 0.5),
+        sprand(3000, 0.5),
+        sprand(3000, 0.5),
+        ["r$x" for x = 1:3000],
+        ["m$x" for x = 1:4000],
+    ),
     sprand(2000, 3000, 0.5),
     sprand(2000, 0.5),
     sprand(2000, 0.5),
-    sprand(3000, 0.5),
-    sprand(3000, 0.5),
-    sprand(3000, 0.5),
-    ["r$x" for x = 1:3000],
-    ["m$x" for x = 1:4000],
 )
diff --git a/test/io/sbml.jl b/test/io/sbml.jl
index ed4f1d7e27fb91e0e1f77226daeb52016086fbb5..8800aa9617f7b017a3212275f5400e68c8914389 100644
--- a/test/io/sbml.jl
+++ b/test/io/sbml.jl
@@ -12,15 +12,20 @@ if cksum != "78692f8509fb36534f4f9b6ade23b23552044f3ecd8b48d84d484636922ae907"
     @warn "The downloaded E Coli core model seems to be different from the expected one. Tests may fail." cksum
 end
 
-@testset "SBML import" begin
-    m = loadSBMLModel(sbmlfile)
+@testset "SBML import and conversion" begin
+    sbmlm = loadSBMLModel(sbmlfile)
+    m = convert(LinearModel, sbmlm)
 
-    @test size(m.C) == (0, 95)
-    @test size(m.S) == (92, 95)
+    @test size(stoichiometry(sbmlm)) == (92, 95)
+    @test size(stoichiometry(m)) == (nMetabolites(sbmlm), nReactions(sbmlm))
     @test length(m.S.nzval) == 380
-    @test length(m.b) == 92
+    @test length.(bounds(sbmlm)) == (95, 95)
+    @test length.(bounds(m)) == (95, 95)
     @test all([length(m.xl), length(m.xu), length(m.c)] .== 95)
 
-    @test m.mets[1:3] == ["M_succoa_c", "M_ac_c", "M_fru_b"]
-    @test m.rxns[1:3] == ["R_EX_fum_e", "R_ACONTb", "R_GLNS"]
+    @test metabolites(m)[1:3] == ["M_succoa_c", "M_ac_c", "M_fru_b"]
+    @test reactions(m)[1:3] == ["R_EX_fum_e", "R_ACONTb", "R_GLNS"]
+
+    cm = convert(CoupledLinearModel, sbmlm)
+    @test nCouplingConstraints(cm) == 0
 end
diff --git a/test/reconstruction/coupling.jl b/test/reconstruction/coupling.jl
index dc279da96e835e3948d864d34e39b463097fefdd..1f152abc49cbd35b642a50a7e9bb3f1154677853 100644
--- a/test/reconstruction/coupling.jl
+++ b/test/reconstruction/coupling.jl
@@ -1,16 +1,17 @@
 @testset "Coupling constraints" begin
-    cp = test_LP()
-    @test size(cp.S) == (4, 3)
-    newCp = addCouplingConstraints(cp, cp.S[end, :], -1.0, 1.0)
+    cp = convert(CoupledLinearModel, test_LP())
+    @test size(cp.lm.S) == (4, 3)
+    @test size(stoichiometry(convert(LinearModel, cp))) == (4, 3)
+    newCp = addCouplingConstraints(cp, stoichiometry(cp)[end, :], -1.0, 1.0)
     @test nCouplingConstraints(cp) + 1 == nCouplingConstraints(newCp)
 
-    newCp = addCouplingConstraints(cp, cp.S[1:2, :], [-1.0; -1.0], [1.0; 1.0])
+    newCp = addCouplingConstraints(cp, stoichiometry(cp)[1:2, :], [-1.0; -1.0], [1.0; 1.0])
     @test nCouplingConstraints(cp) + 2 == nCouplingConstraints(newCp)
 
     nC = nCouplingConstraints(cp)
-    addCouplingConstraints!(cp, cp.S[end, :], -1.0, 1.0)
+    addCouplingConstraints!(cp, stoichiometry(cp)[end, :], -1.0, 1.0)
     @test nC + 1 == nCouplingConstraints(cp)
-    addCouplingConstraints!(cp, cp.S[1:2, :], [-1.0; -1.0], [1.0; 1.0])
+    addCouplingConstraints!(cp, stoichiometry(cp)[1:2, :], [-1.0; -1.0], [1.0; 1.0])
     @test nC + 3 == nCouplingConstraints(cp)
 
     nC = nCouplingConstraints(cp)
@@ -23,6 +24,7 @@
     cp = test_coupledLP()
     nC = nCouplingConstraints(cp)
     newCp = removeCouplingConstraints(cp, 1)
+    @test size(coupling(cp)) == (nC, nReactions(cp))
     @test nC - 1 == nCouplingConstraints(newCp)
     @test nCouplingConstraints(cp) == nC
     newCp = removeCouplingConstraints(cp, [1, 2])
@@ -33,8 +35,10 @@
 
     cp = test_coupledLP()
     changeCouplingBounds!(cp, [3, 1], cl = [-10.0, -20], cu = [10.0, 20])
-    @test cp.cl[[1, 3]] == [-20, -10]
-    @test cp.cu[[1, 3]] == [20, 10]
+    cl, cu = couplingBounds(cp)
+    @test cl[[1, 3]] == [-20, -10]
+    @test cu[[1, 3]] == [20, 10]
     changeCouplingBounds!(cp, [1000, 1001], cl = [-50.0, -60.0])
-    @test cp.cl[[1000, 1001]] == [-50.0, -60.0]
+    cl, cu = couplingBounds(cp)
+    @test cl[[1000, 1001]] == [-50.0, -60.0]
 end